I've written a function that goes through the text file and reads all the data's and prints them out, but the format of displaying data's are wrong and it just prints out data line by line, like this:
james
c 18 6 endah regal
male
0104252455
rodgo.james
kilkil
and what i'm looking for displaying data is something like this (which is not currently happening ):
Name : james
Address : c 18 6
Gender : Male
Contact : 0104252455
Username : rodgo.james
Password : kilkil
and here is the function :
int molgha() {
ifstream in("owner.txt");
if (!in) {
cout << "Cannot open input file.\n";
return 1;
}
char str[255];
while (in) {
in.getline(str, 255); // delim defaults to '\n'
if (in) cout << str << endl;
}
system("pause");
in.close();
}
keep in mind that this text file contains the records of owners registered to the system, hence we may need to print out maybe 3 sets of owner data's with the same pattern without any errors, hence what is the best way to display data's like that continuously ?
You're not printing out the desired labels of Name,Address etc in your code. You have two options -
1) Write out the labels before the data in the actual file itself, and leave the printing code as-is
2) Have a struct or a class with the members name, address etc and a function to print the contents
struct FileEntry{
string name;
string address;
.
.
.
void printContents(){
cout << "Name: " << name << endl;
cout << "Address: " << address << endl;
// etc etc
}
}
If you want to have varying numbers of records per file just put a number at the top of the file, i.e if the file holds 100 records put 100 as the first piece of data to read in and use it in your processing
int numRecords;
ifstream in;
if(in.open("owners,txt")){
numRecords << in;
for(int record = 0; record < numRecords; records++){
//read the info and output it here
}
You want to store your output names names, something like this:
std::vector<std::string> names { "Name", "Address", "Gender", "Contact", "Username", "Password" };
take an interator to it:
auto it = names.begin();
and print in your while loop:
if (in) cout << *it++ << " : " << str << endl;
Just add a array of labels, and print them based on the line you are getting from the file.
const string labels[6] = {
"Name", "Address", "Gender", "Contact", "Username", "Password"
};
int i = 0;
while (in) {
in.getline(str, 255); // delim defaults to '\n'
if (in) {
if (i == 6) i = 0;
cout << labels[i++] << " : " << str << endl;
}
}
So to re-state your question :
How can I add the fields Name: , Address: , etc to the output.
I would suggest the following approach :
Declare the field names in a static array :
const char* fieldNamesArray[6] = { "Name","Address","Gendre", "Contact","Username","Password"};
Inside your read / write function , consume each non-empty lines and assume that all entries have 6 fields and all time in the same order :
int curField=0;
while(in)
{
in.getLine(str,255);
if (strlen(str)>0)
{
cout<< fieldsNamesArray[curField] << " : " << str;
curField++;
}
if (curField>=6)
{
curField=0;
}
}
Related
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 2 years ago.
Improve this question
This is what I tried. I tried strcpy, substituting the value and using in_file again 3 of them can't work. This program is supposed to use the data in a input file and then does functions 1-4 selected by user.
List all products
Search the price of a product
Update the price of a product
Exit
If the user chooses to exit, the program will write the updated data in the array of structures to the file.
The product information includes product number, description and price.
#include <iomanip>
#include <fstream>
#include <cstring>
using namespace std;
typedef struct
{
char product_num[5];
char product_des[29];
float price;
}PRODUCT_TYPE;
int main()
{
ifstream in_file("input practical 12 part d.txt");
if (!in_file)
{
cout << "Error opening input file" << endl;
}
else
{
PRODUCT_TYPE product[50];
int index = -1;
int choice;
in_file >> product[++index].product_num;
cout << "Succesful run" << endl;
cout << "Menu (Type number for the function)" << endl;
cout << "1. List all products\n2.Search the price of a product\n3.Update the price of a product\n4.Exit\n";
cin >> choice;
if (choice == 1)
{
cout << setw(18) << left << "Product Index" << setw(35) << left << "Product Description" << "Price" << endl;
}
else if (choice == 3)
{
cout << "Enter the product number to change its price: ";
cin >> product[index].product_num;
cout << "Enter the new price of the product: ";
cin >> product[index].price;
}
else if (choice == 4)
{
cout << setw(18) << left << "Product Index" << setw(35) << left << "Product Description" << "Price" << endl;
}
while (in_file)
{
in_file >> product[index].product_des >> product[index].price;
if (choice == 1)
{
cout << setw(18) << left << product[index].product_num << setw(35) << left << product[index].product_des << product[index].price << endl;
}
else if (choice == 2)
{
cout << "Type the product number to get the price" << endl;
cout << "Product Number: ";
cin >> product[index].product_num;
cout << "Price: ";
cout << product[index].price << endl;
}
else if (choice == 4)
{
cout << setw(18) << left << product[index].product_num << setw(35) << left << product[index].product_des << product[index].price << endl;
}
in_file >> product[++index].product_num;
}
in_file.close();
out_file.close();
}
return 0;
}```
Unfortunately changes in existing files are not that easy. The problem is that data are stored byte after byte in a file on a disk (sometimes even not that). So, if you have data in your file (always one byte) like the below
Position in file: 0 1 2 3 4 5 9 7 8 9 . . .
Bytes as decimal: . . . 49 50 51 61 62 63 . . .
Bytes as character: . . . 1 2 3 A B C . . .
And you want to update 1 2 3 at position 3 by 1 2 3 4 5 then you would need to shift all folowing bytes in the file by 2 characters, because 12345 is 2 bytes longer than 123. Nobody can do that. And it will not be done automatically.
So, there are basically 2 approaches to solve such problems.
Open the source file -> Read all data into memory -> Close source file -> Do the modifications in memory -> Open source file in overwrite mode -> Write new data.
Use a temporary file. -> Open the source file for input -> Open a temporary file for output -> Read source file line by line -> Do modifications for each read line immediately -> Write result to temp file -> After all source file data have been read, close both files -> Delete the original source file. Rename the tempfile to the old source file name.
(3. If the length of the data, that you want to modifiy, is the same than the old data, then you could move the file write pointer and overwrite the old data. But you need always the same length. So, most often not feasible)
There are of course more solutions, but those 2 approaches are often used.
Please see some pure example codes. Just plain example, unrelated to your code. No productive code. No error checking. Just to give you an idea, how it could work.
Method 1
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
std::vector<std::string> readFile(const std::string& filename) {
// Here we will store all the data from the file
std::vector<std::string> fileData;
// Open the source file
std::ifstream fileStream(filename);
// Read line by line and add it to our fileData
std::string line;
while (std::getline(fileStream, line)) {
fileData.push_back(line);
}
return fileData;
}
void writeFile(std::vector<std::string>& fileData, const std::string& filename) {
// Open file for output
std::ofstream fileStream(filename);
// Write all data to file
for (const std::string& line : fileData)
fileStream << line << '\n';
}
int main() {
// Aproach with read complete file to local variable, modify and the store again
const std::string dataFileName("r:\\test.txt");
// Get file content
std::vector<std::string> data = readFile(dataFileName);
// Now go through all records and do something
for (std::string& line : data) {
// If some condition is met then do something, for example modify
if (line == "Line1") line += " modified";
}
// And then write the new data to the file
writeFile(data, dataFileName);
return 0;
}
Method 2:
#include <iostream>
#include <fstream>
#include <string>
#include <cstdio>
int main() {
// Aproach with temp file, remove and rename, and on the fly change
const std::string dataFileName("r:\\test.txt");
const std::string tempFileName("r:\\temp.txt");
{
// Open the source file with data
std::ifstream dataFileStream(dataFileName);
// Open the temporary file for output
std::ofstream tempFileStream(tempFileName);
// Now read the source file line by line with a simple for loop
std::string line;
while (std::getline(dataFileStream, line)) {
// Identify the line that should be deleted and do NOT write it to the temp file
if (line != "SearchString") { // Or any other condition
// Write only, if the condition is not met
tempFileStream << line << '\n';
}
}
} // The end of the scope for the streams, will call their destructor and close the files
// Now, remove and rename
std::remove(dataFileName.c_str());
std::rename(tempFileName.c_str(), dataFileName.c_str());
return 0;
}
C++ Code
Basically i am trying to take input from a file and store the data in variables, But i am unable to do that because each time i compile this code it compiles successfully but gives a runtime error.(Right Now i have just Data of 3 Students, so i set the condition to run the loop 3 times).
The variable "Name" will get the name from the file, "sap" will get the roll number, "number" will get the number of subjects the user wants to enter marks of (Max 5), and "marks" will enter marks of those subjects.
Variables "SapFile", "NumberFile", and "MarksFile" will get the string data from the file and store them in their respective format variables as mentioned above.
What it does Exactly is read Data from the file to the variables and also prints them, But when it reaches at "i=3" Then instead of this condition becoming false and terminating the Loop and exiting the Function, it gives a runtime error. [Note: It prints the data of 3 students in the file correctly and then gives Runtime error].
The Error Snap is Attaches as follows,
Runtime Error Image
'''
This is My code
void read_in_variables(void)
{
string SapFile = "";
string NumberFile = "";
string MarksFile = "";
int studentCount = 0;
struct Student
{
string Name = "";
int sap = 0;
int number = 0;
int marks[5] = { 0 };
};
Student S[50];
ifstream outFile;
outFile.open("Students.csv", ios::in);
if (outFile.is_open())
{
for (int i = 0; i<3; i++)
{
if (i == 0)
cin.ignore();
getline(outFile, S[i].Name, ',');
studentCount++;
getline(outFile, SapFile, ',');
S[i].sap = stoi(SapFile);
getline(outFile, NumberFile, ',');
S[i].number = stoi(NumberFile);
cout << i + 1 << ". " << S[i].Name << ", " << S[i].sap << ", " << S[i].number;
for (int j = 0; j < (S[i].number - 1); j++)
{
getline(outFile, MarksFile, ',');
S[i].marks[j] = stoi(MarksFile);
cout << ", " << S[i].marks[j];
}
getline(outFile, MarksFile, '\n');
S[i].marks[S[i].number] = stoi(MarksFile);
cout << ", " << S[i].marks[S[i].number];
cout << endl;
}
outFile.close();
if (studentCount == 0)
cout << "\n\nNo Student Records Present.\n\a\n";
}
else
{
cout << "File not Opened !!! ";
}
}
Moreover, when at first i tried to put "outFile.eof()" in the condition statement then it returns false in the beginning and does not even enters in the loop, and Prints "No Student Records Present." as "StudentCount" has Value 0.
[I have included All the Header Files necessary for this function].
Kindly Help me Solve this issue and make this function work perfectly.
So what im trying to do is to allow user to input name, age, education.
If user ended adding data, by entering 's' the program moves to sorting.
If user didnt enter 's' the input loop continues, and user may add more people.
So at line: std::cin>>stop;. I'm opening input stream to check if user entered 's'. If they didn't - this input should be closed, and then new input should start at line: while(std::cin>>name>>age>>education) - to add more people.
My question is how to close this std::cin>>stop; input? If it's not closed, the first character of name will be put into char stop, and name will be lacking the first character.
std::cin.unget() does the trick but its not exactly the purpose it should serve, because if the the type of stop is changed from char to std::string, the whole name will be put into stop variable.
int main()
{
int age;
std::string name, education;
std::vector<Data> zbior;
std::cout << "Enter: name, age, education: ex: Ala 20 primary" << std::endl;
while(std::cin>>name>>age>>education)
{
zbior.push_back(Data(name, age, education));
char stop;
std::cout << "Type s to end input or continue adding data" << std::endl;
std::cin>>stop;
if(stop == 's') break;
else std::cin.unget();
system("cls");
sortManual();
std::string sort;
while (std::cin>>sort) {
if(sort =="ar") { system("cls"); print_young_to_elder(zbior); std::cout << "\n" << std::endl; sortManual();}
if(sort =="am") { system("cls"); print_elder_to_younger(zbior); std::cout << "\n"; sortManual();}
if(sort =="er") { system("cls"); print_Edu_rising(zbior); std::cout << "\n"; sortManual();}
if(sort =="em") { system("cls"); print_Edu_descending(zbior); std::cout << "\n"; sortManual();}
}
}
Please use string not char to read one of the words (like name) and compare it to your "s" and if equal take approprioate action.
I would not reverse input streams or things like that in that simple program as it like adds a layer of complication when it is not needed..
This question already has answers here:
Read file line by line using ifstream in C++
(8 answers)
Closed 6 years ago.
I have the following text file from which I am attempting to read each line and then store the integer component and the string component separately. Here is the text file:
RUID Name
4325 name1
RUID Name
5432 name2
6530 name3
RUID Name
1034 name4
2309 name5
Here is the code I attempting to read with:
int main()
{
// Initialize Lists
LinkedList list1, list2, list3;
// Initialize Counter
int counter = 0;
// Entry containers
const int size = 12;
char entry[size];
string name[size];
string RUID[size];
// BEGIN: "read.txt"
// Open
ifstream studDir;
studDir.open("read.txt");
// Read
while (studDir.is_open())
{
if (studDir.eof())
{
cout << "Reading finished" << endl;
break;
}
else if (!studDir)
{
cout << "Reading failed" << endl;
break;
}
studDir.getline(entry, size);
if (entry != "RUID Name")
{
cout << entry << " " << endl;
}
}
return 0;
}
Could anyone recommend a method that would allow me to ignore the "RUID Name" line as well as separate the integer and string portion of the relevant lines. I've tried several strategies with little success. Also I wish to then write the output of the sorted list to a text file.
You should rewrite your loop like this:
// Entry containers
const size_t size = 12;
std::string entry;
string name[size];
string RUID[size];
size_t index = 0;
// ...
while (index < size && std::getline(studDir,entry)) {
if (entry != "RUID Name") {
cout << entry << " " << endl;
std::istringstream iss(entry);
if(!(iss >> RUID[index] >> name[index])) {
std::cout << "Reading failed" << endl;
break;
}
++index;
}
}
I have a txt file which contains the name and roll number of students. I want to read and display a particular roll number from his file. It shows only the first roll number, but I want to read the roll number of the 2nd person.
That is, if I want to read the roll number of "ss", it shows the roll number of the first person
The program is
#include<iostream.h>
#include<conio.h>
#include<fstream.h>
#include<string.h>
#include<stdio.h>
void student_read()
{
clrscr();
char name[30], n[30], temp[30];
int i, roll_no, code, count=0;
ifstream fin("tt.txt",ios::in|ios::beg);
if(!fin)
{
cout << "cannot open for read ";
return;
}
cout << "Enter the name of student" << "\n";
cin >> n;
while(fin >> name >> roll_no)
{
cout << roll_no << endl;
}
if(string[name] == string[n])
{
cout << "roll no" << "\n" << roll_no;
}
else
cout << "Not found";
}
void main()
{
clrscr();
cout << "Students details is" << "\n";
student_read();
getch();
}
The txt file contains this data:
sourav
123
ss
33
Does you have end of each line in your text file? Does you have sourav 123 ss 33 or sourav 123\nss 33?And this if(n[30]==name[30]) compare only 1 character in string.
You're doing the output of what is in the file already before you even input the name to search for.
Reorder your statements, like this:
cout<<"Enter the name of student"<<"\n";
cin>>n;
while(fin>>name>>roll_no)
{
//...
Also, if you only want to output one name and roll_no, in your loop, you have to check some kind of condition whether to print or not. At the moment, your code should actually print the roll_no of all rows in the file, and possibly sometimes the last one twice.
So the condition you have after the input belongs into the loop.
Additionally, however, you're only comparing the 31st character of the char array (which is actually already out of the bounds of your array variables! Their indices go from 0..29, i.e. even if you allocated a 30 characters array, the ). That means, your condition will be true if the next to last character matches. This place will most likely not be initialized yet, so you compare basically gargabe values and will get unexpected/random results.
If you want to, as the description suggests, want to compare the whole char array, that works differently by the way (not with the == operator, that would only compare pointer addresses), you'd need to use the strcmp function. But even better would be to use std::string instead of char *.
void student_read()
{
clrscr();
std::string name, n, temp;
int i, roll_no, code, count = 0;
std::ifstream fin("tt.txt", ios::in | ios::beg);
if (!fin)
{
std::cout << "cannot open for read ";
return;
}
std::cout << "Enter the name of student" << "\n";
std::cin >> n;
while (fin >> name >> roll_no)
{
std::cout << roll_no << std::endl;
}
if (name == n)
{
std::cout << "roll no" << "\n" << roll_no;
}
else
std::cout << "Not found";
}
int main()
{
clrscr();
std::cout << "Students details is\n";
student_read();
getch();
}