-1

Consider a simple program. It must take string from stdin and save to variable. It is not stated how many lines of input will be taken, but program must terminate if meet newline.

For example: stdin:

abc
abs
aksn
sjja
\n

I tried but it doesn't work. Here is my code:

#include <iostream>
#include <cstring>
#include <cstdio>

using namespace std;
// Constant
#define max 100000
struct chuoi
{
       char word[10];
};
chuoi a[max];

void readStr()
{
    int i=0;
    while ( fgets(a[i].word, 10,stdin) != NULL)
    {
        if (a[i].word[0] == ' ') break;
        a[i].word[strlen(a[i].word)-1] = '\0'; //replaced \n by \0
        i++;
    }
     //length = i;
}
int main()
{
    readStr();
    return 0;
}

So, how to solve this problem?

hoangddt
  • 33
  • 2
  • 7

2 Answers2

3

One alternative here is to use std::getline to get each line. If the line is empty, or the input fails, then exit the loop.

void readStr()
{
    std::string str;

    while ( std::getline(std::cin, str) && str.length() )
    {
        // use the string...
    }
}

Adding the std::getline and use of std::vector to your sample code, and keeping with the spirit of your original sample;

#include <string>
#include <iostream>
#include <vector>

const std::size_t Max = 100000;

struct chuoi
{
    explicit chuoi(std::string const& str) : word(str)
    {
    }

    std::string word;
};

void readStr(std::vector<chuoi>& a)
{
    std::string str;
    while ( std::getline(std::cin, str) && str.length() )
    {
        a.push_back(chuoi(str));
    }
}
void writeStr(std::vector<chuoi> const& a)
{
    for (auto i = a.begin(); i != a.end(); ++i) {
        std::cout << i->word << std::endl;
    }
}
int main()
{
    std::vector<chuoi> a;
    a.reserve(Max);
    readStr(a);
    writeStr(a);
    return 0;
}

To solve you immediate problem, minimal changes in the code can be made as follows;

void readStr()
{
    int i = 0;
    while ( fgets(a[i].word, 10, stdin) != NULL)
    {
        a[i].word[strlen(a[i].word) - 1] = '\0'; // transform the end of line character to NULL
        if (strlen(a[i].word) == 0) {
            break;
        }
        i++;
    }
}

If the standard input will always be used (stdin), the gets function can also be used;

while ( gets(a[i].word) != NULL)
{
    if (strlen(a[i].word) == 0) {
        break;
    }
    i++;
}

Notes;

  • fgets reads until the "enter" key on the stdin but includes the new line character
  • gets also reads until the return, but excludes the new line character
  • Both functions NULL terminate the input
  • Be careful of the form of gets it does not check for buffer overflow conditions
Niall
  • 30,036
  • 10
  • 99
  • 142
2

I would do something like this:

#include <string>
#include <iostream>

int main()
{
    std::string line; // will contain each line of input

    // Stop when line is empty or when terminal input has an error
    while(std::getline(std::cin, line) && !line.empty())
    {
        // do stuff with line
    }
}
Galik
  • 47,303
  • 4
  • 80
  • 117