This program takes in an input, write it on a file character by character, count the amount of characters entered, then at the end copy it to an array of characters. The program works just fine until we get to the following snippet file.getline(arr, inputLength);. It changes the .txt file data and returns only the first character of the original input.
Any ideas?
#include <iostream>
#include <fstream>
using namespace std;
int getLine(char *& arr);
int main() {
char * arr = NULL;
cout << "Write something: ";
getLine(arr);
return 0;
}
int getLine(char *& arr) {
fstream file("temp.txt");
char input = '\0'; //initialize
int inputLength = 0; //initialize
if (file.is_open()) {
while (input != '\n') { //while the end of this line is not reached
input = cin.get(); //get each single character
file << input; //write it on a .txt file
inputLength++; //count the number of characters entered
}
arr = new char[inputLength]; //dynamically allocate memory for this array
file.getline(arr, inputLength); //HERE IS THE PROBLEM!!! ***
cout << "Count : " << inputLength << endl; //test counter
cout << "Array : " << arr << endl; //test line copy
file.close();
return 1;
}
return 0;
}
I see at least two problems with this code.
1) std::fstream constructor, by default, will open an existing file. It will not create a new one. If temp.txt does not exist, is_open() will fail. This code should pass the appropriate value for the second parameter to std::fstreams constructor that specifies that either a new file needs to be created, or the existing file is created.
Related to this: if the file already exists, running this code will not truncate it, so the contents of the file from this program's previous run will have obvious unexpected results.
2) The intent of this code appears to be to read back in the contents temp.txt that were previously written to it. To do that correctly, after writing and before reading it is necessary to seek back to the beginning of the file. This part appears to be missing.
There is no need in dynamic allocation because the std library functions get confused with mixed arguments such as cstring and pointer to cstring.I tested this code in Visual Studio 2015 compiler. It works good. Make sure to include all of the needed libraries:
#include <iostream>
#include <fstream>
#include<cstring>
#include<string>
using namespace std;
void getLine();
int main() {
cout << "Write something: ";
// no need to pass a pointer to a cstring
getLine();
system("pause");
return 0;
}
void getLine() {
char input[100]; // this is a cstring with
//a safe const number of elements
int inputLength; //to extract length of the actual input
//this function requires cstring as a first argument
// and constant length as a second
cin.get(input, 100, '\n'); //get each single character
//cast streamsize into int
inputLength = static_cast<int>(cin.gcount());
//testing input
cout << "Input: \n";
for (int i = 0; i < inputLength; i++)
{
cout << input[i];
}
cout << endl;
char arr[100];
strcpy_s(arr, input);
cout << "Count : " << inputLength << endl; //test counter
cout << "Array : " << endl; //test line copy
for (int i = 0; i < inputLength; i++)
{
cout << arr[i];
}
cout << endl;
// write cstring to a file
ofstream file;
file.open("temp.txt", ios::out);
if (file.is_open())
{
//write only what was entered in input
for (int i = 0; i < inputLength; i++)
file << arr[i];
file.close();
}
else cout << "Unable to open file";
}
Related
I am writing a code that reads an input file of numbers, sorts them in ascending order, and prints them to output. The only thing printed to output is some really freaky symbols.
Here is my code
#include <fstream>
#include <iostream>
using namespace std;
int main()
{
int i, y, temp, num[20];
char file_nameI[21], file_nameO[21];
ofstream outfile;
ifstream infile;
cout << "Please enter name of input file: ";
cin >> file_nameI;
infile.open(file_nameI);
if (!infile)
{
cout << "Could not open input file \n";
return 0;
}
cout << "Please enter name of output file: ";
cin >> file_nameO;
outfile.open(file_nameO);
if (!outfile)
{
cout << "Could not open output file \n";
return 0;
}
for (i = 0; i < 20; i++)
{
y = i + 1;
while (y < 5)
{
if (num[i] > num[y]) //Correction3
{
infile >> temp;
temp = num[i];
num[i] = num[y];
num[y] = temp;
//y++; //Correction4
}
y++;
}
}
for (i = 0; i < 5; i++)
outfile << "num[i]:" << num[i] << "\n";
return 0;
}
Here is my input
6 7 9 0 40
Here is the output
„Ô,üþ 54
H|À°ÀzY „Ô,üþ 0
Problems with your code are already mentioned in the comments but again:
First problem is uninitialized elements of num[20] - elements of num have indeterminate values so accessing any of them triggers undefined behavior. You should first read them from the file or at least initialize them to some default value.
The part of code that should most likely do the sorting is just completely wrong. If you'd like to implement your own function for sorting, you can pick up some well-known algorithm like e.g. quicksort - but C++ Standard Library already provides sorting function - std::sort.
Besides obvious mistakes:
You are using char[] - in C++ it's almost always better to use std::string.
Your static array can only store 20 values and you are reading those from a file. You can use std::vector which can grow when you add more elements than its current capacity. It also automatically fixes the problem with uninitialized elements of num[20].
As mentioned in the comments you can organize your code and improve readability by splitting it into functions.
Here you've got it quickly rewritten. This code uses std::string instead of char[], std::vector to store the numbers and std::sort. If there is something you don't understand here, read SO documentation:
#include <fstream>
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
vector<int> read_file(ifstream& in_file)
{
vector<int> vec;
int value;
while (in_file >> value)
{
vec.push_back(value);
}
return vec;
}
void write_file(ofstream& out_file, const vector<int>& values)
{
for (size_t i = 0; i < values.size(); ++i)
out_file << "value #" << i << ": " << values[i] << '\n';
}
int main()
{
string input_filename, output_filename;
ofstream out_file;
ifstream in_file;
cout << "Please enter name of input file: ";
cin >> input_filename;
in_file.open(input_filename);
if (!in_file)
{
cout << "Could not open input file\n";
return 0;
}
cout << "Please enter name of output file: ";
cin >> output_filename;
out_file.open(output_filename);
if (!out_file)
{
cout << "Could not open output file\n";
return 0;
}
auto numbers = read_file(in_file);
sort(begin(numbers), end(numbers));
write_file(out_file, numbers);
return 0;
}
You might forgot to store values in num array. Just update your code as follows and it will work.
infile.open(file_nameI);
if (!infile){
cout << "Could not open input file \n";
return 0;
} else{
i = 0;
while (infile >> num[i]){
i++;
}
}
I'm working on a code that reads in a C++ source file and converts all ‘<’ symbols to “<” and all ‘>’ symbols to “>”. I wrote out the main method and everything compiled nicely but now that I'm actually writing out my convert function at the top of the program, I'm stuck in an infinite loop and I'm hitting a wall on what the culprit is. Could someone help me out?
I included the whole program in case the problem lies in my I/O coding but I surrounded the function with slashes. Hopefully I won't get flamed.
#include <iostream>
#include <fstream>
#include <cstdlib>
#include <string>
#include <cstring>
using namespace std;
//FUNCTION GOES THROUGH EACH CHARACTER OF FILE
//AND CONVERTS ALL < & > TO < or > RESPECTIVELY
//////////////THIS IS THE FUNCTION IN QUESTION//////////
void convert (ifstream& inStream, ofstream& outStream){
cout << "start" << endl;
char x;
inStream.get(x);
while (!inStream.eof()){
if (x == '<')
outStream << "<";
else if (x == '>')
outStream << ">";
else
outStream << x;
}
cout << "end" << endl;
};
///////////////////////////////////////////////////////////////////////////
int main(){
//FILE OBJECTS
ifstream inputStream;
ofstream outputStream;
string fileName;
//string outFile;
//USER PROMPT FOR NAME OF FILE
cout << "Please enter the name of the file to be converted: " << endl;
cin >> fileName;
//outFile = fileName + ".html";
//ASSOCIATES FILE OBJECTS WITH FILES
inputStream.open(fileName.c_str());
outputStream.open(fileName + ".html");
//CREATES A CONVERTED OUTPUT WITH <PRE> AT START AND </PRE> AT END
outputStream << " <PRE>" << endl;
convert(inputStream, outputStream);
outputStream << " </PRE>" << endl;
inputStream.close();
outputStream.close();
cout << "Conversion complete." << endl;
return 0;
}
It isn't a good approach to manipulate a file while you're reading it. The right way is, first read the whole file, store the data, manipulate the stored data, and then update the file. Hope this code will help you :)
void convert()
{
int countLines = 0; // To count total lines in file
string *lines; // To store all lines
string temp;
ifstream in;
ofstream out;
// Opening file to count Lines
in.open("filename.txt");
while (!in.eof())
{
getline(in, temp);
countLines++;
}
in.close();
// Allocating Memory
lines = new string[countLines];
// Open it again to stroe data
in.open("filename.txt");
int i = 0;
while (!in.eof())
{
getline(in, lines[i]);
// To check if there is '<' symbol in the following line
for (int j = 0; lines[i][j] != '\0'; j++)
{
// Checking the conditon
if (lines[i][j] == '<')
lines[i][j] = '>';
}
i++;
}
in.close();
// Now mainuplating the file
out.open("filename.txt");
for (int i = 0; i < countLines; i++)
{
out << lines[i];
if (i < countLines - 1)
out << endl;
}
out.close();
}
I'm currently beginning on C++ and trying to make a function that can open a .txt file, read it, and save its words in an array (each word being a protein sequence).
Unfortunately I don't succeed at calling the argument containing the name of the file (argv[1]) in the function.
Can anyone spot errors in my code or in the way I implemented this ?
Thanks in advance, you will find the code and the error messages below :
Libraries
So here are my librairies and 'shortcuts'.
// Librairies
#include <iostream>
#include <string>
#include <fstream>
// Alias
using std::cout;
using std::endl;
using std::string;
The function
Now this is the function, note that filename is supposed to be a string containing argv[1] (the name of a .txt file specified at execution) :
string SequenceChoice(int n, string filename); // Function returning a string
std::ifstream sequenceFile (filename); //Opens the file specified on execution
if ( sequenceFile.is_open() )
{
cout<<"File opened"<<endl;
string tmp;
int i = 0;
while( sequenceFile >> tmp ) // Counts the number of sequences (words)
{
i++;
}
string allchains[i]; // Creates an array of strings, to save all the words
sequenceFile.clear();
sequenceFile.seekg(0, sequenceFile.beg); // Replaces the cursor at the beginning of the file
i=0;
while( sequenceFile >> allchains[i]) // Saves each word as a string in an array
{
cout << allchains[i] << tmp;
i++;
}
sequenceFile.close();
cout<< "File closed"<<endl;
}
else
{
cout << "Error: Cannot open file" << endl;
}
return allchains[n]; // returns the 'n'th word (n being specified when calling the function
// end of the function
Main
Now the main function, I'm not sure if doing string filename = argv[1] works, but I get less errors when I keep this step instead of putting argv[1] as an argument of my SequenceChoice() function.
int main(int argc, char *argv[]) {
if(argc >= 2)
{
string filename = argv[1];
cout << SequenceChoice( 2, filename ) << endl; // I expect it to give me the 3rd word of a .txt file for example.
}
else
{
cout << "Error : No file" << endl;
}
return 0;
}
The error message I get
Error message
The link above is a picture of the error message I get when I compile, I've been searching for hours on the internet how to resolve this, unfortunately I could'nt manage to have the code working. There's probably an error of type with the way I deal with argv[], but I failed at solving it so any help and comments would be greatly appreciated.
Please try changing following line
string SequenceChoice(int n, string filename); // Function returning a string
to
string SequenceChoice(int n, string filename) { // Function returning a string
You are trying to write a function but the ; is terminating your function and body is not starting. It should work. Also please read a book carefully.
This page lists very good books for all experience levels.
Try this :
string SequenceChoice(int n, string filename)
{
std::ifstream sequenceFile (filename); //Opens the file specified on execution
if ( sequenceFile.is_open() )
{
cout<<"File opened"<<endl;
string tmp;
int i = 0;
while( sequenceFile >> tmp ) // Counts the number of sequences (words)
{
i++;
}
string allchains[i]; // Creates an array of strings, to save all the words
sequenceFile.clear();
sequenceFile.seekg(0, sequenceFile.beg); // Replaces the cursor at the beginning of the file
i=0;
while( sequenceFile >> allchains[i]) // Saves each word as a string in an array
{
cout << allchains[i] << tmp;
i++;
}
ifs.close();
cout<< "File closed"<<endl;
}
else
{
cout << "Error: Cannot open file" << endl;
}
return allchains[n];
}
Here is fully functioning code:
You can compare it with yours.
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
string SequenceChoice(int n, string filename){ // Function returning a string
std::ifstream sequenceFile (filename); //Opens the file specified on execution
if ( sequenceFile.is_open() )
{
cout<<"File opened"<<endl;
string tmp;
int i = 0;
while( sequenceFile >> tmp ) // Counts the number of sequences (words)
{
i++;
}
string allchains[i]; // Creates an array of strings, to save all the words
sequenceFile.clear();
sequenceFile.seekg(0, sequenceFile.beg); // Replaces the cursor at the beginning of the file
i=0;
while( sequenceFile >> allchains[i]) // Saves each word as a string in an array
{
cout << allchains[i] << tmp;
i++;
}
sequenceFile.close();
cout<< "File closed"<<endl;
return allchains[n]; // returns the 'n'th word (n being specified when calling the function
}
else
{
cout << "Error: Cannot open file" << endl;
}
return NULL;
// end of the function
}
int main(int argc, char *argv[])
{
if(argc >= 2)
{
string filename = argv[1];
cout << SequenceChoice( 2, filename ) << endl; // I expect it to give me the 3rd word of a .txt file for example.
}
else
{
cout << "Error : No file" << endl;
}
}
Thanks to your answers I managed to solve my problem, apart from some syntax errors in the code the argument filename in the function was a string, and as argv[] is an array of pointers. So it just couldn't work to consider them as the same type.
Here is a working version of the function, for those it could help :
string SequenceChoice(int n, char* argv[])
{
std::ifstream sequenceFile (argv[1]); //Opens the file specified on execution
if ( sequenceFile.is_open() )
{
cout<< " .File opened. \n" <<endl;
string tmp;
int i = 0;
while( sequenceFile >> tmp ) // Counts the number of sequences (words)
{
i++;
}
cout << " " << i << " chains in the .txt file : \n" << endl;
string allchains[i]; // Creates an array of strings, to save all the words
sequenceFile.clear();
sequenceFile.seekg(0, sequenceFile.beg); // Replaces the cursor at the beginning of the file
i=0;
while( sequenceFile >> allchains[i]) // Saves each word as a string in an array
{
cout << " --- Chain "<< i + 1 << " --- : " << allchains[i] << endl;
i++;
}
sequenceFile.close();
cout << "\n .File closed. \n" << endl;
return allchains[n];
}
else
{
cout << "Error: Cannot open file" << endl;
return NULL;
}
}
And finally the new main function :
int main(int argc, char *argv[]) {
if(argc >= 2)
{
string filename = argv[1];
cout << SequenceChoice( 2, argv ) << endl; // Shows the 3rd word of the file, as an example.
}
else
{
cout << "Error : No file" << endl;
}
return 0;
}
Thanks for your help and have a great day !
I have been having some problems with my code. I was asked to input elements from an .dat file into an array. For class we have to do this for various files without knowing how many elements will be in each file. The only thing we know is that here will never be more then 5000 elements per file.
One of my input file has the following elements:
5.675207 -0.571210
0.728926 0.666069
2.290909 0.751731 2.004545 0.907396
0.702893 0.646427 5.909504 -0.365045
2.082645 0.871841 5.597107 -0.633507
6.117769 -0.164663 6.091736 -0.190282
5.571074 -0.653433 4.503719 -0.978307
3.983058 -0.745620
3.670661 -0.504729
5.857438 -0.413001
When I run my code:
#define _CRT_NONSTDC_NO_DEPRECATE
#include <iostream>
#include <fstream>
#include <cstring>
using namespace std;
int main(int argc, char * argv[])
{
ifstream fin;
ofstream fout;
if (argc < 3)
{
cout << "Incorrect usage: prog.exe filenname number" << endl;
cout << "Exiting now, please try again." << endl;
return -1;
}
fin.open(argv[1]);
if (!fin)
{
cout << "Error opening file \"" << argv[1] << "\", exiting." << endl;
return -1;
}
fout.open(argv[2]);
int count = 0;
int word;
double points[5000];
while (fin >> word)
{
fin >> points[count];
++count;
}
fout << "Numer of points is: " << count/2 << endl;
for (int i = 0; i < count; i++)
{
fout << points[i] << " ";
}
fin.close();
fout.close();
return 0;
}
I outputted the elements just to make sure that they were properly inputted. I get the following and I don't know why.
0.675207 0.57121
0.728926 0.666069
0.290909 0.751731 0.004545 0.907396
0.702893 0.646427 0.909504 0.365045
0.082645 0.871841 0.597107 0.633507
0.117769 0.164663 0.091736 0.190282
0.571074 0.653433 0.503719 0.978307
0.983058 0.74562
0.670661 0.504729
0.857438 0.413001
The first digit is converted to a 0 for some reason and the negative ones become positive. Would anyone know why this is occurring?
int word;
is doing you no favours. First it's an integer so fin >> word only reads the integer portion of the inputs. 5.675207 is read as 5. the .675207 is left in the file stream for fin >> points[count]. Words isn't stored anywhere to the 5 is discarded but the .675207 lives on as 0.675207 in points[0].
Where the negative signs are going I didn't bother trying to figure out because
while (fin >> points[count])
{
++count;
}
fixes everything.
When you read in the numbers from the the file you are extracting them as "word" and then storing them as "points". "word" is an integer and "points" is a double, this will give you unexpected behavior. The compiler should give you warnings about this.
#include <iostream>
#include <iomanip>
#include <cstdlib>
#include <fstream>
using namespace std;
void make_array(ifstream& num, int (&array)[50]);
int main()
{
ifstream file; // variable controlling the file
char filename[100]; /// to handle calling the file name;
int array[50];
cout << "Please enter the name of the file you wish to process:";
cin >> filename;
cout << "\n";
file.open(filename);
if (file.fail()) {
cout << "The file failed to open.\n";
exit(1);
} else {
cout << "File Opened Successfully.\n";
}
make_array(file, array);
file.close();
return (0);
}
void make_array(ifstream& num, int (&array)[50])
{
int i = 0; // counter variable
while (!num.eof() && i < 50) {
num >> array[i];
i = i + 1;
}
for (i; i >= 0; i--) {
cout << array[i] << "\n";
}
}
I am trying to read values from a file to an array using fstream. When I try to display the contents of the array, I get 2 really big negative numbers, and then the contents of the file.
Any ideas what I did wrong?
Your use of num.get(array[i]) doesn't match any of its signatures. See get method description. What you want is this:
array[i] = num.get();
As discussed in the comments, you try to read an integer which is encoded as text. For this, you need to use operator>> (which reads any type encoded as string) instead of get (which reads a single byte):
num >> array[i];