int main() {
int len;
cout<<"Enter the size of dynamic array you want: ";
cin>>len;
int file_len;
int *new_num;
ifstream in("test.txt");
in.seekg(0, ios::end);
file_len = in.tellg();
in.close();
if(file_len>len)
{
int times= file_len/len;
for(int i=0; i<times; i++)
{
ifstream in("test.txt");
if(i==0)
{
char *n_ch = new char[len];
in.seekg(0, ios::cur);
in.read(n_ch, len);
cout<<n_ch<<"\'";
delete n_ch;
} else {
char *n_ch = new char[len];
in.seekg(i*len, ios::cur);
in.read(n_ch, len);
cout<<",,"<<n_ch<<"..";
delete n_ch;
}
}
in.close();
}
return 0;
}
What I want to do is to get the nth to (n+len)th letters and put them into an array, and then print them.
right now I'm getting this result,
the content of test.txt is:
ABCDEABCDE
qwerty poiuy
zxcvb
mnbhhg
ooooo
I can't find the reason why I am getting extra letters, which i guess is the first letter of the next letters.
Is there a way to solve this problem?
After in.read(n_ch, len) you need to use gcount() to see how many characters were actually read. Say your file has 37 characters, and you're reading in chunks of 10: the last read will only return 7 characters and you want to make sure you only try to write 7 to the output (you can use cout.write(n_ch, gcount());).
You are reading C strings. C strings are null terminated, that is they need a null character at the end to indicate how long the string is. Your code doesn't do that. Try this
char *n_ch = new char[len + 1]; // one extra for the null terminator
in.seekg(0, ios::cur);
in.read(n_ch, len);
n_ch[len] = '\0'; // add the null terminator
cout<<n_ch<<"\'";
delete n_ch;
Related
I am trying to read a string from a binary file but cant seem to get it to work. I am a pretty new to c++. Can anybody help please? Thanks.
string Name = "Shaun";
unsigned short int StringLength = 0;
int main()
{
StringLength = Name.size();
ofstream oFile("File.txt", ios::binary|ios::out);
oFile.write((char*)&StringLength, sizeof(unsigned short int));
oFile.write(Name.c_str(), StringLength);
oFile.close();
StringLength = 0;
Name = "NoName";
ifstream iFile("File.txt", ios::binary|ios::in);
if(!iFile.is_open())
cout << "Failed" << endl;
else
{
iFile.read((char *)&StringLength, sizeof(unsigned short int));
iFile.read((char *)&Name, StringLength);
}
cout << StringLength << " " << Name << endl;
system("Pause>NUL");
return 0;
}
This is the problematic line.
iFile.read((char *)&Name, StringLength);
You are reading the char* part of a std::string directly into the memory of Name.
You need to save both the size of the string as well as the string so that when you read the data, you would know how much memory you need to read the data.
Instead of
oFile.write(Name.c_str(), StringLength);
You would need:
size_t len = Name.size();
oFile.write(&len, sizeof(size_t));
oFile.write(Name.c_str(), len);
On the way back, you would need:
iFile.read(&len, sizeof(size_t));
char* temp = new char[len+1];
iFile.read(temp, len);
temp[len] = '\0';
Name = temp;
delete [] temp;
you need to create a buffer of char type.
char *buffer = new char[size];
Then use your buffer as the parameter to read function
iFile.read(buffer, size);
Instead of this
iFile.read((char *)&Name, StringLength);
Try this:
Name.resize(StringLength);
iFile.read((char *)&Name[0], StringLength);
Your original line overwrites the string object data from the beginning, which may contain the string length and capacity, for instance, instead of the character data. Also you don't resize the string appropriately to be able to contain the data.
Conceptually, you need to understand the data stream which you are reading. Not everything use ASCII which uses a byte size of 8 bits. I also notice you did not set bit size read which can be as little as one bit to as large as {R, B, G, A} color set. Using your basic 2 dimensional reiteration structured code.
I basically have a txt file that looks like this...
High Score: 50
Player Name: Sam
Number Of Kills: 5
Map
Time
I want to store everything before the : or whitespace after Map and Time into one array and everything after in another. For both Map and Time, there is nothing after and so I want to store the whitespace as null.
So far, I have managed to read and store all this information into a temp array. However, it is separating that I am having trouble with. This is my code:
istream operator >> (istream &is, Player &player)
{
char **temp;
char **tempNew;
char lineInfo[200]
temp = new char*[5];
tempNew = new char*[5];
for (int i=0; i<5; i++)
{
temp[i] = new char[200];
is.getline(lineInfo, sizeof(lineInfo));
int length = strlen(lineInfo);
for (int z=0; z < length; z++)
{
if(lineInfo[z] == '= ' ){ //HOW DO I CHECK IF THERE IS NOTHING AFTER THE LAST CHAR
lineInfo [length - (z+1)] = lineInfo [length];
cout << lineInfo << endl;
strncpy(temp[i], lineInfo, sizeof(lineInfo));
}
else{
tempNew[i] = new char[200];
strncpy(tempNew[i], lineInfo, sizeof(lineInfo));
}
}
}
If what you need is to find ':'
#include <cstring>
and just
auto occurance = strstr(string, substring);
Documentation here.
if occurance is not a null ptr, then see if occurance is at the end of the line from get line. If not, your value is everything after that :
Much easier with std::string.
// Read high score
int high_score;
my_text_file.ignore(10000, ':');
cin >> high_score;
// Read player name
std::string player_name;
my_text_file.ignore(10000, ':');
std::getline(my_text_file, player_name);
// Remove spaces at beginning of string
std::string::size_type end_position;
end_position = player_name.find_first_not_of(" \t");
if (end_position != std::string::npos)
{
player_name.erase(0, end_position - 1);
}
// Read kills
unsigned int number_of_kills = 0;
my_text_file.ignore(':');
cin >> number_of_kills;
// Read "Map" line
my_text_file.ignore(10000, '\n');
std::string map_line_text;
std::getline(my_text_file, map_line_text);
// Read "Text" line
std::string text_line;
std::getline(my_text_file, text_line);
If you insist on using C-style strings (arrays of char), you will have to use more complex and less safe functionality. Look up the following functions:
fscanf, strchr, strcpy, sscanf
I am trying to read a string from a binary file but cant seem to get it to work. I am a pretty new to c++. Can anybody help please? Thanks.
string Name = "Shaun";
unsigned short int StringLength = 0;
int main()
{
StringLength = Name.size();
ofstream oFile("File.txt", ios::binary|ios::out);
oFile.write((char*)&StringLength, sizeof(unsigned short int));
oFile.write(Name.c_str(), StringLength);
oFile.close();
StringLength = 0;
Name = "NoName";
ifstream iFile("File.txt", ios::binary|ios::in);
if(!iFile.is_open())
cout << "Failed" << endl;
else
{
iFile.read((char *)&StringLength, sizeof(unsigned short int));
iFile.read((char *)&Name, StringLength);
}
cout << StringLength << " " << Name << endl;
system("Pause>NUL");
return 0;
}
This is the problematic line.
iFile.read((char *)&Name, StringLength);
You are reading the char* part of a std::string directly into the memory of Name.
You need to save both the size of the string as well as the string so that when you read the data, you would know how much memory you need to read the data.
Instead of
oFile.write(Name.c_str(), StringLength);
You would need:
size_t len = Name.size();
oFile.write(&len, sizeof(size_t));
oFile.write(Name.c_str(), len);
On the way back, you would need:
iFile.read(&len, sizeof(size_t));
char* temp = new char[len+1];
iFile.read(temp, len);
temp[len] = '\0';
Name = temp;
delete [] temp;
you need to create a buffer of char type.
char *buffer = new char[size];
Then use your buffer as the parameter to read function
iFile.read(buffer, size);
Instead of this
iFile.read((char *)&Name, StringLength);
Try this:
Name.resize(StringLength);
iFile.read((char *)&Name[0], StringLength);
Your original line overwrites the string object data from the beginning, which may contain the string length and capacity, for instance, instead of the character data. Also you don't resize the string appropriately to be able to contain the data.
Conceptually, you need to understand the data stream which you are reading. Not everything use ASCII which uses a byte size of 8 bits. I also notice you did not set bit size read which can be as little as one bit to as large as {R, B, G, A} color set. Using your basic 2 dimensional reiteration structured code.
I m reading a file and I would like to extract all of its contents and store them into a single char in C++. I know it can be done with strings however I cannot use strings and need to resort to char instead. I can I concatenate multiple chars to one char variable?
Here is what I've tried so far:
string str = "";
ifstream file("c:/path.....");
while (file.good())
{
str += file.get();
}
const char* content = str.c_str();
printf("%c", *content);
but this just gave me the first letter of the file and that's it.
If also tried:
ifstream file("c:/path.....");
char c = ' ';
char result[100];
while (file.good())
{
c= file.get();
strcat(result,c);
}
but this gave me runtime errors all the time.
For the second try you gave in your question (which I guess from your other hints, is what you finally want), you can try the following as a quick fix:
ifstream file("c:/path.....");
char c[2] = { 0, 0 };
char result[100] = { 0 };
for (int i = 0; file && (i < 99); ++i)
{
c[0] = file.get();
strcat(result,c);
}
Since using strcat() might not be very efficient for this use case, I think a better implementation would directly write to the result buffer:
ifstream file("c:/path.....");
char result[100] = { 0 };
for (int i = 0; file && (i < 99); ++i)
{
result[i] = file.get();
}
In your first code block:
const char* content = str.c_str();
printf("%c", *content);
prints only the first character of the string because *contents dereferences the
pointer to the (first character of) the string, and %c is the printf-format for
a single character. You should replace that by
printf("%s", content);
to print the entire string. Or just use
std::cout << str;
Maybe something like that :
char result[100];
int i = 0;
while (file.good())
{
c= file.get();
if(i<100)
result[i++]=c;
}
result[i]='\0';
There a lot of things to improve in this solution (what would you do if there more then 99 chars in your file, file.good() not the best option for loop condition, and so on...). Also it is much better to use strings.I don't know exactly why you can't use them, but just in case you change your mind you can read your file like that :
std::string line;
while ( getline(stream, line)) {
process(line);
}
You can create std::strings of your characters and concatenate them:
char c1 = 'a';
char c2 = 'b';
std::string concatted = std::string(1, c1) + std::string(1, c2);
This works because of the fill std::string constructor, see the reference.
Obviously, you are new to the c++ or at least you're using some strange terminology.
First of all, I advice you to read some c++ literature for beginners (you can find list of it on stackoverflow). Then you will understand all the conceptions of strings in c++.
Second, use this code to read file content and store it in a char*.
FILE *f = fopen("path to file", "r");
fseek(f, 0, SEEK_END);
long fsize = ftell(f);
fseek(f, 0, SEEK_SET);
char *content = new char[fsize + 1];
fread(content, fsize, 1, f);
fclose(f);
content[fsize] = 0;
cout << "{" << content <<"}";
delete content;
I am a beginner in working with files. What I want to do in my code is to get a name from the user, and hide it in a .bmp picture. And also be able to get the name again from the file. But I want to change the characters into ASCII codes first ( that's what my assignment says)
What I tried to do is to change the name's characters to ASCII codes, and then add them to the end of the bmp picture which I'll open in binary mode. And after adding them, i want to read them from the file and be able to get the name again.
This is what I've done so far. But I am not getting a proper result. All i get is some meaningless characters. Is this code even right?
int main()
{
cout<<"Enter your name"<< endl;
char * Text= new char [20];
cin>> Text; // getting the name
int size=0;
int i=0;
while( Text[i] !='\0')
{
size++;
i++;
}
int * BText= new int [size];
for(int i=0; i<size; i++)
{
BText[i]= (int) Text[i]; // having the ASCII codes of the characters.
}
fstream MyFile;
MyFile.open("Picture.bmp, ios::in | ios::binary |ios::app");
MyFile.seekg (0, ios::end);
ifstream::pos_type End = MyFile.tellg(); //End shows the end of the file before adding anything
// adding each of the ASCII codes to the end of the file.
int j=0;
while(j<size)
{
MyFile.write(reinterpret_cast <const char *>(&BText[j]), sizeof BText[j]);
j++;
}
MyFile.close();
char * Text2= new char[size*8];
MyFile.open("Picture.bmp, ios:: in , ios:: binary");
// putting the pointer to the place where the main file ended and start reading from there.
MyFile.seekg(End);
MyFile.read(Text2,size*8);
cout<<Text2<<endl;
MyFile.close();
system("pause");
return 0;
}
Many flaws are in your code, one important is:
MyFile.open("Picture.bmp, ios::in | ios::binary |ios::app");
Must be
MyFile.open("Picture.bmp", ios::in | ios::binary |ios::app);
^ ^
| |
+-----------+
Second, use std::string instead of C-style strings:
char * Text= new char [20];
should be
std::string Text;
Also, use std::vector to make a array:
int * BText= new int [size];
should be
std::vector<int> BText(size);
And so on...
You write int (which is 32 bits) but read char (which is 8 bits).
Why not write the string as-is? There's no need to convert it to an integer array.
And also, you don't terminate the array you read into.
your write operation is incorrect, you should pass the complete text directly
MyFile.write(reinterpret_cast <const char *>(BText), sizeof (*BText));
Also, casting your string to ints and back to chars will insert spaces between your characters which you don't take into account in your reading operation