so the task for this code is to copy students' names and grades from an csv excel sheet into xcode and then put them into arrays and put them into a new excel sheet. The problem that i seem to be having is that the getline does not go to the next line. To make sure that there wasn't an error somewhere in this code that would cause that to happen, I wrote a very small and completely different program to see how getline works and found that it does not skip to the next line. In fact, if I raise the character amount to a high number, it will just copy in the entire excel info into the array. Here's my code:
#include <iostream>
#include <fstream>
#include <cstring>
#include <cstdlib>
using namespace std;
char line[80];
string students[100];
int grades[50][20];
char *p;
int r;
int q;
void read_sheet();
void print_sheet();
int main() {
read_sheet();
print_sheet();
return 0;
}
void read_sheet(){
ifstream file1("/Users/JohnnyD/Downloads/Project_MAC101.csv");
file1.getline(line, 79); // this puts everything from the first line of the
// excel sheet into the array line
for(r=0;r<50||(!file1.eof());r++){ // this is a loop that goes up to
// either the amount of students
//(50 is max) or the end of the
file1.getline(line, 79); // this is suppose to put everything
//from the second line into the array
// line, but I don't think it is doing
// that.
p=strtok(line,","); // this takes everything from the first
// line that is before the comma and
//puts it into p.(should be only a single
// student's name
students[r]=p; // this puts the name into the array
// called students
cout << students<<endl; // this is only a test to see if the names
// are going properly to the array. I
// wouldn't normally have this in the code.
// This is where I found out that it's not
// skipping to the next line because the
// output just spits out "name" over and
// over again which means that it never got
// passed the first word in the excel sheet.
// ("name" is the first word in the first
// line in the excel sheet)
for(q=0;q<20;q++){ // this is a loop that goes to the end of
// the column where 20 is the max amount
// of grades
p=strtok(NULL,","); // puts each grade before the comma into p.
if(p==NULL) // if it's the end of the line, break out
break; //of the loop.
grades[r][q]=atoi(p); // this changes the string to integer and then
// puts it into the array grades
}
}
file1.close();
}
void print_sheet(){
ofstream file2("testing.csv");
for(int y=0;y<=r;y++){
file2<<students[y];
for(int h=0;h<q;h++){
file2<<grades[y][h];
}
file2<<endl;
}
file2.close();
}
This is the code that I used to test to see if getline was actually moving to the next line.
#include <iostream>
#include <fstream>
#include <cstring>
#include <cstdlib>
using namespace std;
char line[80];
int main() {
ifstream file1("/Users/JohnnyD/Downloads/Project_MAC101.csv");
file1.getline(line, 79);
cout << line<<endl;
file1.getline(line, 79); // shouldn't this then go to the next line?
cout << line<<endl; // It doesn't. It only repeats the first getline
return 0;
}
The usual idiom for reading from a file is to use a while statement.
In your case, you can limit it with another variable:
const unsigned int maximum_records = 50U;
unsigned int record_count = 0U;
std::string text_line;
// ...
while (getline(datafile, text_line) && (record_count < maximum_records))
{
//...
++record_count;
}
If either the file operation failed or the maximum records have been reached, the input session will terminate.
Related
I've created a program that takes C++ code in one text file and outputs all of the comments from that code in another text file, however I've encountered a special situation, where the program does not do the necessary task. While it does extract most of the comments, it does not extract single line comments which are inside of a block comment.
Here is the C++ source code:
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main()
{
fstream fin; //file that will be read
fstream fout; //file that will be written
string row; // string variable which will store each row of the code
string comment; // string which will store the comment
string blockCommentStart = "/*";
string lineCommentStart = "//"; // the beginning symbols of comments so that they could be identified in the text file
string result;
fin.open("code.txt", ios::in);
fout.open("endresult.txt", ios::out);
if(!fin) cout << "File not found" << endl;
if(!fout) cout << "File not found" << endl;
getline(fin, row); //reads the first row from the file
while(fin)
{
for(int i = 0;i<row.size();i++)
{
while (row[i]!= '/') //goes through the row until it finds the '/' symbol
{
if(i>row.size()) break;
i++;
}
if (i>row.size()) break; //checks if the end of the row has been reached
if(row[i+1] =='/' || row[i+1]=='*') //checks if the next symbol is the start of a comment
{
result = row[i];
result+= row[i+1];
}
if(result!="")
{
comment = ""; //creates a single line comment
if(result==lineCommentStart)
{
while (i<row.size())
{
comment+=row[i]; //the comment string adds the symbols of the comment
i++;
}
fout << comment << endl; //comment gets output in the endresult.txt file
comment=""; //after the output, it is renewed to the beginning stage
break;
}
comment = ""; //creates a block comment
if(result==blockCommentStart || result==lineCommentStart)
{
comment=row[i];
comment+=row[i+1]; //writes the comment symbols in the output file
i+=2; //jumps over the comment symbols
while(row[i]!='/') //adds symbols to the comment whilst it hasn't reached the end symbols
{
if(i>=row.size())
{
fout << comment << " "; //comment gets output in the endresult.txt file
getline(fin, row); //reads the next line
comment = ""; //comment string gets renewed for the new row
i=0; //moves the iterator back to the beginning position
}
comment+=row[i];
i++;
}
fout << comment << endl;
}
result = ""; //results gets renewed to the beginning stage
}
}
getline(fin,row); // reads the next line
};
fin.close();
fout.close(); //after the work is done, the files are closed
}
Here is the content of the test file code.txt:
// merge algorithm example
#include <iostream> // std::cout
#include <algorithm> // std::merge, std::sort
#include <vector> // std::vector
using namespace std;
int main () {
vector<int> first = {1,5,8};
int second[] = {2,3,7,9};
vector<int> v(7);
merge (first.begin(),first.end(),second,second+4,v.begin());
std::cout << "The resulting vector contains:";
for(auto &i: v) cout<<i<<" "; cout<<endl;
}
/*
Comment which is in
multiple
// single line inside block
lines or a block
*/
//comment
Here is the result of the program(endresult.txt):
// merge algorithm example
// std::cout
// std::merge, std::sort
// std::vector
/* Comment which is in multiple /
//comment
So as one can see, the single line comment inside the block comment breaks the entire block comment structure. I would really appreciate any help or insight on how to solve this problem. Thank you!
EDIT: I've tried solving this further by replacing the
while(row[i]!='/')
line in the code near the blockComment segment with
while(row[i]!='/' || row[i-1]!='*')
and it now seems to include the single line comment however the formatting is a little wonky because the entire block comment then gets output together in a single line. Is there an easy solution to this, something like adding an endline after every row that is read?
I have two text files like these:
11.txt:
1 5.66
2 4.95
3 2.55
4 0.99
5 2.87
NB.txt:
1 2 3 4 5
4 5 3 2 1
3 4 5 1 2
I have written the below code to fine, for example, "1" from File 1, and search it in File 2, then substitute "1" with "5.66". and repeat it for other numbers, i.e. 2,3,4,5. but I don't know why it doesn't work. additionally, it doesn't read the first line of 11.txt.
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main ()
{
string line;
double AtomId, Atom_radius,search ;
ifstream AtomId_file ("11.txt");
string namefile;
if (AtomId_file.is_open()){
for (int linenox = 0; getline (AtomId_file,line) && linenox < 6; linenox++){
if (linenox == 0) AtomId_file>>AtomId>>Atom_radius;
}
cout<<"AtomId: "<<AtomId<<" Atom_radius: "<<Atom_radius<<endl;
cout<<namefile<<"\n";
}
ifstream NB("NB.txt");
size_t pos;
if (NB.is_open())
{
search = AtomId;
getline(NB,line);
pos=line.find(search);
if(pos!=string::npos)
{
search = Atom_radius;
cout <<"Found!";
}
}
ofstream myfile;
myfile.open ("12.txt");
myfile << search << "\n";
}
the output in 12.txt is:
2
instead of :
5.66 4.95 2.55 0.99 2.87
0.99 2.87 2.55 4.95 5.66
2.55 0.99 2.87 5.66 4.95
I understand that your are new to C++.
I analyzed your code and put in tons of comments, where the errors are. You need to change your design. Before starting to type in code, you must first write down, what should be done. Then, and this is most important, you think (without taking any language into consideration) how you can solve the problem. This is most important. Also for you later programming career. The design is most important. So think 3 hours, how it could be done. Search possible design solutions in the internet. Write it on a piece of paper or somewhere.
Then, after hours of thinking, select an apropriate language and check, how it could be implemented.
I show a standard C++ solution below. You will not understand it immediately. So please try to understand the design first. Then lookup all used C++-statements in the internet and try to understand.
Read some good C++ books, before starting to code.
Please see first your commented code:
#include <iostream>
#include <fstream>
#include <string>
using namespace std; // You should not use this line at all. Use qualified names.
int main()
{
string line;
double AtomId, Atom_radius, search; // These variables are not initalized
ifstream AtomId_file("r:\\11.txt");
string namefile;
if (AtomId_file.is_open()) { // You should not use is_open but simply if (AtomId_file)
// Here you have a loop running from 0,1,2,3,4,5. That are 6 loops. But you have only 5 lines in your sourcefile
// The you read one line, each time the loops runs. So in the beginning, this will read the first line
for (int linenox = 0; getline(AtomId_file, line) && linenox < 6; linenox++) {
// And only for the first loop event, when linenox==0, you read then next line "2 4.95"
// So you read already lines. But not more.
// ypu need to read line by line (only one per loop) and then store the result in an appropriate STL Container
if (linenox == 0) AtomId_file >> AtomId >> Atom_radius;
}
// Since you assigned the data only once, the values will be 2, 4.95
// They will never change
cout << "AtomId: " << AtomId << " Atom_radius: " << Atom_radius << endl;
// The variable namefile has never been initailized and is always emtpy, So ""
cout << namefile << "\n";
}
ifstream NB("r:\\NB.txt");
size_t pos; // Not initialized
if (NB.is_open()) // Not recommended. Use "if (NB) instead". In general, use more meaningful variable names
{
search = AtomId; // search is now 2 and never somthing else
getline(NB, line); // Read exactly one (and only this one time) a line containing 1, 5.66
pos = line.find(search); // So, 2 will never be found
if (pos != string::npos) // Always false, can never be true
{
search = Atom_radius; // Will never be executed
cout << "Found!"; // Will never be executed
}
}
ofstream myfile; // You can write directly ofstream myfile("12.txt");
myfile.open("12.txt");
myfile << search << "\n"; // And the output will always be 2.
}
And here is a correct and working example:
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <unordered_map>
#include <vector>
#include <iterator>
int main() {
// Open the file 11.txt and check, if it could be opened
if (std::ifstream file11("11.txt"); file11) {
// Define variable id and attribute and initialize them to theire default values.
unsigned int id{};
double attribute{};
// Here we will store all values (id, attribute) of all lines that we read in the follwing loop
std::unordered_map<unsigned, double> replacement{};
// Read in a llop ALL lines and extract id and attribute, and, check if this worked
while (file11 >> id >> attribute) {
// Create a new replacement value for id
replacement[id] = attribute;
}
// So, now, all data from file 11.txt is read and stored.
// We will now read the next file and store the data
// Open next input file NB.txt and check, if that worked
if (std::ifstream fileNB("NB.txt"); fileNB) {
// And already now, open output file 12.txt and check, if open worked
if (std::ofstream myfile("12.txt"); myfile) {
// Read a complete line and check, if that worked. Read all lines in a loop
for (std::string line; std::getline(fileNB, line); ) {
// Put the line in a std::istringstream, so that we can extract each single value
std::istringstream iss(line);
// We will store the single values of the just read line into a vector
// This we do, because we do not know, how many values will be in that line
// We use a so called iterator, to iterate over all elements in the just read line
// The result will be stored in a vector
// The istream_iterator will call the ">>"-operator, until the line is empty
// For the vector, we use its range constructor
std::vector values(std::istream_iterator<unsigned>(iss), {});
// Now go through all values, replace them and out the result into the output file
for (const unsigned& u : values) myfile << replacement[u] << " ";
myfile << "\n";
}
}
}
}
return 0;
}
Of course there are many other possible solutions
So I have two simple questions. One is my function okay for reading a text file composed of one number on each line and passing it an array inside main()? And is the text file opening/closing properly or do I not understand the code?
And secondly, I can't seem to fill my array correctly. There's 92 numbers/lines, but I can only seem to get 91 elements. It seems to skip the first number, but I'm not sure why. When I'm debugging I can see "number" reading the the first line, but I don't know where it goes.
The text file is 92 numbers with decimals, with a number in each line like this..and the first number is in the first line, no space above and no vertical space between the numbers.
31.11
25.22
...
int getTempData(double temperatures[]) {
ifstream input("pgm6.txt");
if (!input)
return 1; // closes input file
string number;
while (input >> number)
for (int i = 0; i < 91; i++)
{
input >> temperatures[i];
}
}
and inside main()
const int ARRAY_SIZE = 91;
double temperatures[ARRAY_SIZE];
getTempData(temperatures);
Edit: Thanks so much for the help everyone. I learned my lesson in not using code I don't quite understand from here: https://www.reddit.com/r/learnprogramming/comments/2wwv6i/c_creating_writing_to_and_displaying_text_files/
#include <fstream> // Instead of <iostream>
#include <string>
using namespace std; // Nothing too much wrong with this...
int main() {
ifstream input("input.txt"); // Open the file "input.txt" for reading
(if = input file)
if ( !input ) // Did the file open correctly?
return 1;
ifstream output("output.txt"); // Open the file "output.txt" for writing
(of = output file)
if ( !output ) // Did the file open correctly?
return 1; // C++ automatically closes the input file!
string word;
**while ( input >> word )** // Read a word while the file isn't at its
end
output << word << '\n'; // Write the word on its own line
// C++ automatically closes the output file
// C++ automatically closes the input file
}
What you are trying to achieve seems to boil down to this:
#include <fstream>
int getTempData(double temperatures[]) {
std::ifstream input("pgm6.txt");
int i;
for (i = 0; i < 92 && input >> temperatures[i]; i++) {
// deliberate empty line
}
// input will close file on exiting function
return i; // returns number of elements found
}
int main() {
const int ARRAY_SIZE = 92;
double temperatures[ARRAY_SIZE];
getTempData(temperatures);
}
while (input >> number)
This reads the first number and throws it away. Simply remove this line of code.
Also, you should probably add error checking to input >> temperatures[i];. And your function needs to return something if all is well -- currently there is no return statement at the end. Also, your loop only collects 91 elements.
not sure what i'm doing wrong but this is my code
int main (){
int marks [100];
int i=0;
ifstream inputfile;
ofstream outputfile;
inputfile.open("data.txt");
if(!inputfile.is_open())
{
cout<< "File did not open"<< endl;
return 0;
}
cout<<"Marks in File:"<<endl;
while (marks [i] != -1)
{
inputfile>>marks[i];
cout << marks[i] <<endl;
i++;
}
return 0;
}
the output is messed up and returns stuff that was never in the data file to begin with
Here is the minimal code for reading data from a file and write it to console. Description is added as comments
#include <fstream>
#include <sstream>
#include <string>
#include <iostream>
using namespace std;
int main()
{
ifstream configrecord("D:\\Temp\\temp.txt"); // opening the file named temp for reading.
if(configrecord.good()) // check whether the file is opened properly.
{
string line;
while (getline(configrecord, line)) // reading a line from file to std::string
{
cout << line; // printing the line, if you want it to store in an array, you can use the std::string::data() api to get the character pointer.
}
configrecord.close(); // closing the file after reading completed
}
}
If we translate your code to English, we get:
Check if the current array element is -1, if it is, break the loop.
Read the value into the current array element.
Output the value.
Move to the next array element and repeat.
Notice a big problem: We're checking if the value is -1 before we actually read it. We need to reverse the order of steps 1 and 2 so that we get:
Read the value into the current array element.
Check if the current array element is -1, if it is, break the loop.
Output the value.
Move to the next array element and repeat.
We can do this by using true as our loop condition and then using an if statement to check if the inputted value is -1 later in the loop, using break to break the loop if it is.
#include <fstream>
#include <iostream>
//using namespace std; is considered bad practice
int main()
{
std::ifstream inFile("input.txt");
int marks[100];
//check if file is open stuff...
for(int i = 0; true; i++)
{
inFile >> marks[i];
if(marks[i] == -1) break;
std::cout << marks[i] << '\n'; //endl flushes the buffer, unnecessary here.
}
}
Of Note: it is good practice that if you use an if statement, you also include an else statement. Also, your while loop is confusing, because it stops if it encounters negative one, so I am assuming you know that integer -1 is not in the file.
int n = -1;
if(!inputfile.is_open())
{
cout<< "File did not open"<< endl;
}
else
{
cout<<"Marks in File:"<< endl;
while(!inputfile.eof()){ // .eof is bad practice, but for this instance it works.
File >> marks[n];
n++; // Essentially the size of the array (Number of values), keeping track of how many values there are will assist you in the output process.
}
}
When you are done reading the file, you should close it and then use the data in the array.
inputfile.close();
Lastly, in order to output an array of data, you must use a for loop or some type of iterator to access the values stored in the array.
for(int i=0; i < n ; i++) // Output array. Where array size is less than n.
{
cout << marks[i] << " "; // " " inputs a space in between each word.
}
I tried to make a code that reads from text file called aisha
This is a new file I did it for as a trial for university
but it worked =)
Its about Removing stopwords from the file
and apply casefolding to it
It tried doing that many times
and finally now I could do now
and then the code stores the read text on an array and then removes the stopwords from it
but now I nead to make the case folding step
the problem that this code reads the text file word by word
I want to read it char by char so I can apply casefolding to each char
is there ant way to make the code read the aisha file char by char ?
#include <iostream>
#include <string>
#include <fstream>
int main()
{
using namespace std;
ifstream file("aisha.txt");
if(file.is_open())
{
string myArray[200];
for(int i = 0; i < 200; ++i)
{
file >> myArray[i];
if (myArray[i] !="is" && myArray[i]!="the" && myArray[i]!="that"&& myArray[i]!="it"&& myArray[i]!="to"){
cout<< myArray[i]<<" ";
}
}
}
system("PAUSE");
return 0;
}
If you declare your array as an array of char instead of array of strings, the extraction operator shall automatically read char.
Also you will have to be careful because the >> operator by default skips the whitespace characters. If you want to read the whitespaces also, then you should add noskipws before reading the characters.
file >> std::noskipws;
The C++ way to do this is explained at this link: http://www.cplusplus.com/reference/istream/istream/get/
#include <iostream> // std::cin, std::cout
#include <vector> // store the characters in the dynamic vector
#include <fstream> // std::ifstream
int main () {
std::ifstream is("aisha.txt"); // open file and create stream
std::vector <char> stuff;
while (is.good()) // loop while extraction from file is possible
{
char c = is.get(); // get character from file
if (is.good())
std::cout << c; // print the character
stuff.push_back(c); // store the character in the vector
}
is.close(); // close file
return 0;
}
Now you basically have every character of the file stored in the vector known as stuff. You can now do your modification to this vector, for it is a far easier internal representation of data. Also, you have access to all the handy STL methods.
Use Whole string instead of reading char by char
using readline function.