将字符串拆分为向量;的话

发布于 2024-12-20 06:30:51 字数 1790 浏览 2 评论 0原文

加速C++(书)中,我发现这段代码是相同的程序,但程序本身的处理不同,这让我在某些方面感到困惑。

下面的代码,很明显,它会在用户包含文件结束符后根据用户输入逐一(通过循环)输出每个单词,然后结束程序。

int main()
{
    string s;
    while (cin >> s)
        cout << s << endl;
    return  0;
}

与上面的代码不同,此代码会将每个单词存储在一个向量中,然后使用索引 i 和 j 来检测非空白字符,并且真正的问题是,我不明白向量是如何发生的。

向量中的空白是什么?一个元素?

起初,我认为程序将遍历每个字符,因为我认为空格是字符(其中ij< /code>功能是为了),然后,书上说它会通过每个单词进行,我不知道如何自己测试这个,就像我可以看到编译器中的内部过程一样本身..

vector<string> split(const string& s)
{
    vector<string> ret;
    typedef string::size_type string_size;
    string_size i = 0;

    // invariant: we have processed characters [original value of i, i) 
    while (i != s.size())
    {
        // ignore leading blanks
        // invariant: characters in range [original i, current i) are all spaces
     while (i != s.size() && isspace(s[i]))
         ++i;

     // find end of next word
     string_size j = i;
     // invariant: none of the characters in range [original j, current j)is a space
     while (j != s.size() && !isspace(s[j]))
         j++;
         // if we found some nonwhitespace characters 
         if (i != j) {
             // copy from s starting at i and taking j - i chars
             ret.push_back(s.substr(i, j - i));
             i = j;
         }
    }
    return ret;
}

int main() {
    string s;
    // read and split each line of input 
    while (getline(cin, s)) {
        vector<string> v = split(s);

        // write each word in v
        for (vector<string>::size_type i = 0; i != v.size(); ++i)
             cout << v[i] << endl;
    }
    return 0;
}

From Accelerated C++(book), I found this code which is identical program, but the processed in program itself is different, and confused me on some part.

The code below, well, obviously it will output each word one-by-one(by loops) based on user input after the user included end-of-file, then, end the program.

int main()
{
    string s;
    while (cin >> s)
        cout << s << endl;
    return  0;
}

Unlike code above, this one will store each word in a vector, then use index i and j to detect the non-whitespace character, and the real question is, I don't understand how it happens with the vector.

What is whitespace in vector? An element?

At first, I thought the program will proceed through each character, because I thought the whitespace is character(which i and j functionality is for), then, the book come and said it proceed through each word, I don't know how to test this myself, like I can see how the inner process in the compiler itself..

vector<string> split(const string& s)
{
    vector<string> ret;
    typedef string::size_type string_size;
    string_size i = 0;

    // invariant: we have processed characters [original value of i, i) 
    while (i != s.size())
    {
        // ignore leading blanks
        // invariant: characters in range [original i, current i) are all spaces
     while (i != s.size() && isspace(s[i]))
         ++i;

     // find end of next word
     string_size j = i;
     // invariant: none of the characters in range [original j, current j)is a space
     while (j != s.size() && !isspace(s[j]))
         j++;
         // if we found some nonwhitespace characters 
         if (i != j) {
             // copy from s starting at i and taking j - i chars
             ret.push_back(s.substr(i, j - i));
             i = j;
         }
    }
    return ret;
}

int main() {
    string s;
    // read and split each line of input 
    while (getline(cin, s)) {
        vector<string> v = split(s);

        // write each word in v
        for (vector<string>::size_type i = 0; i != v.size(); ++i)
             cout << v[i] << endl;
    }
    return 0;
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

感情旳空白 2024-12-27 06:30:51

您上面发布的代码不会根据空格将一行文本拆分为单词,而是将一行文本拆分为字符。但是,前提是代码实际上是可编译的并且没有缺少任何必要的大括号({})。 编辑:实际上,它是否分割单词或单个字符取决于大括号的位置,底线是代码无法编译。

以下是代码的固定版本,只需移动 中的最后一个 if 语句即可拆分每个单词,而不是每个字符 split 在它的直接 while 块之外:

#include <iostream>
#include <vector>
using namespace std;

vector<string> split(const string& s)
{
   vector<string> ret;
   typedef string::size_type string_size;
   string_size i = 0;

   // invariant: we have processed characters [original value of i, i) 
   while (i != s.size()) {
      // ignore leading blanks
      // invariant: characters in range [original i, current i) are all spaces
      while (i != s.size() && isspace(s[i]))
         ++i;

      // find end of next word
      string_size j = i;
      // invariant: none of the characters in range [original j, current j)is a space
      while (j != s.size() && !isspace(s[j]))
         j++;

      // if we found some nonwhitespace characters 
      if (i != j) {
         // copy from s starting at i and taking j - i chars
         ret.push_back(s.substr(i, j - i));
         i = j;
      }
   }
   return ret;
}

int main() {
   string s;
   // read and split each line of input 
   while (getline(cin, s)) {
      vector<string> v = split(s);

      // write each word in v
      for (vector<string>::size_type i = 0; i != v.size(); ++i)
      cout << v[i] << endl;
   }
   return 0;
}

传递给 splitstring 会发生什么:

  • 虽然字符串中仍然有字符 ( <代码>而(我!= s.size()))
    • 当我们从字符串中读取空格时while (i != s.size() && isspace(s[i]))
      • 递增计数器,直到到达单词的开头 (++i)
    • 将单词的结尾设置为单词的开头 (string_size j = i)
    • 当我们仍在这个单词内并且没有达到空格时 (while (j != s.size() && !isspace(s[j])))
      • 增加指示单词结尾的计数器 (j++)
    • 如果有一些非空白字符 - 结尾大于开头 (if (i != j))
      • 从单词的起点到终点创建一个子字符串 (s.substr(i, j - i)),并将该单词添加到向量< /code> (ret.push_back(..)).

    • 冲洗并重复。

The code you posted above does not split a line of text into words, based on whitespace, it instead splits a line into characters. However, that's if the code was actually compilable and not missing any necessary braces ({, }). EDIT: Actually whether it splits words or individual characters depends on where the braces go, bottom line is that the code doesn't compile.

Here is a fixed version of the code that splits each word, rather than each character, by simply moving the last if statement in split outside of it's immediate while block:

#include <iostream>
#include <vector>
using namespace std;

vector<string> split(const string& s)
{
   vector<string> ret;
   typedef string::size_type string_size;
   string_size i = 0;

   // invariant: we have processed characters [original value of i, i) 
   while (i != s.size()) {
      // ignore leading blanks
      // invariant: characters in range [original i, current i) are all spaces
      while (i != s.size() && isspace(s[i]))
         ++i;

      // find end of next word
      string_size j = i;
      // invariant: none of the characters in range [original j, current j)is a space
      while (j != s.size() && !isspace(s[j]))
         j++;

      // if we found some nonwhitespace characters 
      if (i != j) {
         // copy from s starting at i and taking j - i chars
         ret.push_back(s.substr(i, j - i));
         i = j;
      }
   }
   return ret;
}

int main() {
   string s;
   // read and split each line of input 
   while (getline(cin, s)) {
      vector<string> v = split(s);

      // write each word in v
      for (vector<string>::size_type i = 0; i != v.size(); ++i)
      cout << v[i] << endl;
   }
   return 0;
}

What happens to the string passed to split is:

  • While still characters in the string (while (i != s.size()))
    • While we're reading a space from the string while (i != s.size() && isspace(s[i]))
      • Increment the counter until we get to the start of a word (++i)
    • Set the end of the word as the start of the word (string_size j = i)
    • While we're still inside this word and not up to a space (while (j != s.size() && !isspace(s[j])))
      • Increment the counter indicating the end of the word (j++)
    • If there are some non-whitespace characters - end is greater than the start (if (i != j))
      • Create a sub-string from the start point to the end point of the word (s.substr(i, j - i)), and add that word to the vector (ret.push_back(..)).
    • Rinse and repeat.
对你而言 2024-12-27 06:30:51

如果您只是根据空间进行分割,那么您不需要编写自定义方法。 STL 为您提供多种选择。

        std::string line;
        std::vector<std::string> strings;
        while ( std::getline(std::cin, line))
        {
             std::istringstream s ( line);
             strings.insert(strings.end(), 
                 std::istream_iterator<std::string>(s),  
                 std::istream_iterator<std::string>());
        }

     //  For simplicity sake using lambda.   
        std::for_each(strings.begin(), strings.end(), [](const std::string& str)
        {
            std::cout << str << "\n";
        });

If you are just splitting based on space, then you don't need write a custom method. STL has options for you.

        std::string line;
        std::vector<std::string> strings;
        while ( std::getline(std::cin, line))
        {
             std::istringstream s ( line);
             strings.insert(strings.end(), 
                 std::istream_iterator<std::string>(s),  
                 std::istream_iterator<std::string>());
        }

     //  For simplicity sake using lambda.   
        std::for_each(strings.begin(), strings.end(), [](const std::string& str)
        {
            std::cout << str << "\n";
        });
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文