Here is my code.
#include <iostream>
#include <fstream>
#include <cstdlib>
using namespace std;
int main ( ){
ifstream inFile;
char date1[8], date2[8];
int dayTemp1[24], dayTemp2[24];
inFile.open("weatherdata.txt");
if(inFile.fail()){
cout << "File failed to open.";
exit(1);
}
inFile >> date1 >> date2;
cout << date1 << endl;
cout << date2 << endl;
inFile.close();
return 0;
}
The first two lines of the weatherdata.txt file are:
01/04/13
01/05/13
date1 is supposed to contain the first date but when printed it only prints the '\n' character (an empty line).
I don't know what is going on with the code as to why it is skipping the first date line.
Any and all help is appreciated. I'm a beginner to C++.
use std::string instead:
#include <string>
std::string date1;
std::string date2;
//...
inFile >> date1 >> date2;
OR
std::getline(inFile, date1);
std::getline(inFile, date2);
#billz gave you a solution to the problem, so I'll provide an explanation:
The problem was that your char arrays allocated exactly 8 bytes (or characters in this case) but did not leave room for the obligatory null byte (\0). My assumption is that's causing undefined behavior, and when you print you're not getting the correct output because of this. For example, on Linux I'm not getting the first line as blank, I actually get:
01/04/1301/05/13
01/05/13
This was a clear indicator to me the the insertion did not stop when it reached the presumed null byte. The solution is to allow your char arrays hold at least 9 bytes.
Using std::string is beneficial in this context as it avoids this problem completely (it is a container of a dynamically-sized string). Its size will accompany the extra characters (as well as the null byte).
Related
#include <iostream>
#include <string>
using namespace std;
int main()
{
int num;
cin >> num;
string s;
getline(cin, s);
cout << s << " " << num << endl;
return 0;
}
In this code if I input 3 and press enter, then s takes an empty string.
1) If it is taking the first character as a newline, then is there a possible solution of taking line as input after taking an integer as input?
2) If my input is 4567artyu then how it is deciding whether 7 has to go into the s or num ?
I recommend that you always read complete lines of input from your users. It will cause the least confusion.
Ask for input.
Use std::getline to read a line of input.
If you don't want a string but, say, an integer, use std::stoi or (more general) boost::lexical_cast to safely convert the input to your desired target type. This is where you catch poor inputs and complain at the user.
I don't think that many users, if prompted for a number, would expect that entering 42bananas would be accepted as 42 and the bananas part be “remembered” for later. It will most likely be a typo and the user will be happy to be asked to correct it.
For taking line as input after taking integer as input you can consider removing the stray '\n' character from the stream.
#include <iostream>
#include <string>
using namespace std;
int main()
{
int num;
cin >> num;
getchar();
string s;
getline(cin, s);
cout << s << " " << num << endl;
return 0;
}
This will do the trick.
For second question, it reads 4567 as integer, it will continue to read it as integer until limit of int is reached and if limit is reached it will not consider anything after that. Then it will put the maximum value of int in the variable num and null int the string s. If limit is not reached, then string will remain in the input stream as it is, and will be fetched by variable s.
Try using cin.clear before you accept string
I've been trying to read some information in from a .txt file in C++ but it's not all working like I expect. Here is some example code:
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
char words[255];
int value = 0;
ifstream input_stream("test.txt");
input_stream >> value;
input_stream.getline(words, 256);
cout << value << endl;
cout << words << endl;
}
And test.txt contains:
1234
WordOne WordTwo
What I expect is for the code to print the two lines contained in the text file, but instead I just get:
1234
I've been reading about getline and istream but can't seem to find any solutions so any help would be appreciated.
Thanks
The newline character remains in the input stream after the read of the integer:
// Always check result to ensure variables correctly assigned a value.
if (input_stream >> value)
{
}
Then, the call to getline() reads the newline character and stops, producing an empty string. To correct, consume the newline character before calling getline() (options include using getline() or ignore()).
Note there is a version std::getline() that accepts a std::string as its argument to avoid using a fixed sized array of char, which is used incorrectly in the posted code.
ifstream's getline method gathers input until one of two options is hit. Either a terminating character or the size passed in is reached. In your case, the newline terminator is encountered before the size is reached.
Use another getline to retrieve the second line of text.
Reference
The problem you are seeing is that the first newline after 1234 is not consumed by input_stream>>(int); so the next getline only reads to the end of that file.
This is a very constructed scenario, commonly found in schoolwork. The more common scenario when reading a textfile is to consider the entire file as linebased text.
In this case the more convenient
string line;
while( std::getline( input_stream, line ) ){
}
is appropriate, and way less error prone.
The textfile would commonly have a predefined format. Perhaps name = value lines, and are parsed as such after the line is read from the file.
Here is a somewhat corrected version of your original code:
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
char words[256]; // was 255
int value = 0;
ifstream input_stream("test.txt");
input_stream >> value;
input_stream.ignore(); // skip '\n'
input_stream.getline(words, 256);
cout << value << endl;
cout << words << endl;
}
Also, I would advise you to use a string instead of a char[] and use the other getline function.
Our professor gave us this assignment, where we have a .txt file with the following format:
John 23
Mary 56
Kyle 99
Gary 100
...etc. etc.
What we have to do is read the file, and store the names and scores in parallel arrays.
This is turning out to be a bit more challenging to me than I anticipated. What is confusing me, when searching around stack, is all the different libraries people use to do this. Our Prof just wants us to use string, fstream, and sstream to do this.
Below is what I've come up with so far, it compiles perfectly, splits the scores from the names but stores them in the same array:
#include <string>
#include <sstream>
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
const int SIZE = 50;
string names[SIZE];
int score [SIZE];
short loop = 0;
string line;
ifstream inFile("winners.txt");
if (inFile.is_open())
{
while(!inFile.eof())
{
istream& getline(inFile >> line);
names[loop] = line;
cout << names[loop] << endl;
loop++;
}
inFile.close();
}
else cout << "Can't open the file" << endl;
return 0;
}
I'm not looking for someone to solve my HW problem, I just want a push in the right direction!
If you want to read two things for each line of input, it seems reasonable to have two "read" statements:
std::string name;
inFile >> name;
int score;
inFile >> score;
std::cout << "Read score " << score << " for name " << name << '\n';
...then you can do that repeatedly until you've read the entire file.
Edit: After you get the basic logic worked out, you might want to think about error handling. For example, what is appropriate behavior for your program if the input file doesn't contain 50 pairs of (name, score)? How can you change your code to get that behavior?
Each line in the file consists of a name and a score separated by whitespace. You're reading each line but not splitting it into its parts (the name and the score).
Ideally you would use a vector for this, but since it seems that you were asked to use arrays we'll stick with arrays. What you have above looks good until you start reading entries. A more idiomatic way to accomplish this is to use std::getline, i.e.
ifstream inFile( "winners.txt" );
std::string line;
while( std::getline( inFile, line )) {
// Do work here.
}
Inside the loop you need to split the line on the space. Without solving the problem for you, I suggest you take a look at the find and substr functions of the string class: here. They will give you everything you need to solve the problem.
This is a very strange issue. I'm trying to print a large text file, it's a Wikipedia entry. It happens to be the page on Velocity. So, when I tell it to print the file, it prints "In", when it should print "In physics, velocity is etc, etc etc".
Here's the code I'm using to print out:
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
ifstream wiki;
wiki.open("./wiki/velocity.txt");
char* wikiRead;
wiki >> wikiRead;
cout << wikiRead << endl;
wiki.close();
}
Please help.
wiki >> wikiRead;
The default delimiter for stream is space, so when the stream encounters a space, it simply stops reading, that is why it reads only one word.
If you want the stream to read all words, the you've to use a loop as:
char* wikiRead = new char[1024]; //must allocate some memory!
while(wiki >> wikiRead)
{
cout << wikiRead << endl;
}
wiki.close();
delete []wikiRead; //must deallocate the memory
This will print all the words in the file, each on a new line. Note if any of the word in the file is more than 1024 character long, then this program would invoke undefined behavior, and the program might crash. In that case, you've to allocate a bigger chunk of memory.
But why use char* in the first place? In C++, you've better choice: Use std::string.
#include<string>
std::string word;
while(wiki >> word)
{
cout << word << endl;
}
wiki.close();
Its better now.
If you want to read line-by-line, instead of word-by-word, then use std::getline as:
std::string line;
while(std::getline(wiki, line))
{
cout << line << endl;
}
wiki.close();
This will read a complete line, even if the line contains spaces between the words, and will print each line a newline.
You ask the stream to read the (binary) value of a pointer (probably 4 bytes, depending on your machine architecture), then you ask it to print the text pointed to by those 4 bytes!
I wonder why you ignored the compiler warning (most of the modern compiler warns you about using uninitialized variables). How about this?
ifstream wiki;
wiki.open("./wiki/velocity.txt");
char wikiRead[255];
wiki >> wikiRead;
cout << wikiRead << endl;
wiki.close();
Alternatively I'd suggest you to use string object with getline to get a single line of text.
string str;
getline(wiki, str);
The >> operator applied to a char * reads only one word. Moreover, you're reading into an uninitialized pointer, which is not valid. Usually std::string, not char *, is used for string processing in C++.
If you only want to print the file's contents, you can hook the file's buffer directly to std::cout:
int main() {
std::ifstream wiki("./wiki/velocity.txt");
std::cout << wiki.rdbuf() << '\n';
}
If you want to put the contents into an automatically-allocated string, use std::getline with the delimiter disabled.
int main() {
std::ifstream wiki("./wiki/velocity.txt");
std::string wiki_contents;
getline( wiki, wiki_contents, '\0' /* do not stop at newline */ );
std::cout << wiki_contents << '\n'; // do something with the string
}
Since you want to read a large file, reading it block by block is a better way.
ifstream wiki;
wiki.open("./wiki/velocity.txt");
const int buf_size = 1024;
char* wikiRead = 0;
int cnt = 1;
do
{
wikiRead = realloc( wikiRead, bufsize*cnt );
wiki.Read( wikiRead + (bufSize*(cnt-1)), buf_size ); //appends to reallocated memory
cnt++;
}while( !wiki.eof())
wikiRead[(bufSize*(cnt-2)) + wiki.gcount() + 1] = '\0'; // null termination.
wiki.Close();
cout << wikiRead;
delete[] wikiRead;
The operator>> is designed to only read one word at a time. If you want to read lines, use getline.
#include <iostream>
#include <fstream>
#include<string>
using namespace std;
int main()
{
ifstream wiki;
wiki.open("./wiki/velocity.txt");
string wikiRead;
while (getline(wiki, wikiRead))
{
cout << wikiRead << endl;
}
wiki.close();
}
i have a little problem on writing the string into a file,
How can i write the string into the file and able to view it as ascii text?
because i am able to do that when i set the default value for str but not when i enter a str data
Thanks.
#include <iostream>
#include <fstream>
#include <cstring>
using namespace std;
int main()
{
fstream out("G://Test.txt");
if(!out) {
cout << "Cannot open output file.\n";
return 1;
}
char str[200];
cout << "Enter Customers data seperate by tab\n";
cin >> str;
cin.ignore();
out.write(str, strlen(str));
out.seekp(0 ,ios::end);
out.close();
return 0;
}
Please use std::string:
#include <string>
std::string str;
std::getline(cin, str);
cout << str;
I'm not sure what the exact problem in your case was, but >> only reads up to the first separator (which is whitespace); getline will read the entire line.
Just note that >> operator will read 1 word.
std::string word;
std::cin >> word; // reads one space seporated word.
// Ignores any initial space. Then read
// into 'word' all character upto (but not including)
// the first space character (the space is gone.
// Note. Space => White Space (' ', '\t', '\v' etc...)
You're working at the wrong level of abstraction. Also, there is no need to seekp to the end of the file before closing the file.
You want to read a string and write a string. As Pavel Minaev has said, this is directly supported via std::string and std::fstream:
#include <iostream>
#include <fstream>
#include <string>
int main()
{
std::ofstream out("G:\\Test.txt");
if(!out) {
std::cout << "Cannot open output file.\n";
return 1;
}
std::cout << "Enter Customer's data seperated by tab\n";
std::string buffer;
std::getline(std::cin, buffer);
out << buffer;
return 0;
}
If you want to write C, use C. Otherwise, take advantage of the language you're using.
I can't believe no one found the problem. The problem was that you were using strlen on a string that wasn't terminated with a null character. strlen will keep iterating until it finds a zero-byte, and an incorrect string length might be returned (or the program might crash - it's Undefined Behavior, who knows?).
The answer is to zero-initialize your string:
char str[200] = {0};
Supplying your own string as the value of str works because those in-memory strings are null-terminated.