简体   繁体   中英

Read from file to string

Well, firstly, I know I'm using stdio.h to read a file with C++, but please disregard it, I need to do it this way.

I have this file:

5
peter
josh
edward
mary
lois

And I need to read the first number (easy):

int np;

FILE *myfile = fopen("myfile.txt", "r");
fscanf(myfile, "%d", &np);

And then I need to read the following np names:

string people[np];
for (int i = 0; i < np; i++) {
  fscanf(myfile, "%s", &people[i]);
  fscanf(myfile, "\n");
}

However, I'm getting a SEGFAULT. When I used gdb, I got this:

Program received signal SIGSEGV, Segmentation fault.
0x00007ffff7b6e603 in std::basic_ostream<char, std::char_traits<char> >& std::operator<< <char, std::char_traits<char>, std::allocator<char> >(std::basic_ostream<char, std::char_traits<char> >&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) () from /usr/lib/libstdc++.so.6

In my opinion, I think it's because I have an array of strings, and I'm read char*, how can I save the lines as strings using stdio.h file reading commands?

string people[np];
fscanf(myfile, "%s", &people[i]);

There's two of your problems right there. (There are more problems than these, but we'll just focus on these.)

1) C++ doesn't support variable-length arrays. Feel free to use them if you a programming in some other language that does -- g++ with extensions, for example. But if you have a requirement to write a C++ program, you'll need to do something else. Try, for example,

std::vector<std::string> people(np);

2) fscanf requires a char* , not a string* This is the bug that is actually causing your segfault, and there's really no good way to deal with this. The following, while still buggy, may be good enough for your needs:

char buffer[256];
fscanf(myfile, "%s", buffer);
people[i] = buffer;

EDIT : As I read my answer months later, I need to add the C++ idiomatic way of doing this:

int np;
std::cin >> np;

// copy all remaining names
std::vector<std::string> people;
std::copy((std::istream_iterator<std::string>(std::cin)),
           std::istream_iterator<std::string>(),
           std::back_inserter(people));


// Or, (c++11 only) copy exactly "np" names
std::vector<std::string> people;
std::copy_n((std::istream_iterator<std::string>(std::cin)),
           np,
           std::back_inserter(people));

In you program, you are taking the address of the string class, not the address of a character buffer. fscanf needs a character buffer (array of charaters) into which to copy the string. You need to read the string into a temporary buffer then assign it.

char tempBuffer[1024];
string people[np];

for (int i = 0; i < np; i++) 
{      
  fscanf(myfile, "%s", tempBuffer);
  fscanf(myfile, "\n");
  people[i] = tempBuffer;
}    

The = operator for the string class can take a character buffer and then it makes a copy of it.

There may be a way to assign it directly to a string, but I cannot recall a way of being able to do that offhand.

首先将内容读取为c字符串,然后(之后)从中构造std:strings。

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM