This question already has answers here:
c++: how to print new line without carriage return [duplicate]
(2 answers)
Closed 2 years ago.
I have two c++ exes communicating over iostream. First exe sends a stream of chars (or bytes) and second intercepts this and decodes them.
exe1.exe emits chars:
void main()
{
for (int i = 0; i < 256; ++i)
cout << static_cast<char>(i);
}
exe2.exe takes them in:
void main()
{
FILE* pipe = _popen("exe1.exe", "rb");
while (!feof(pipe))
cout << static_cast<int>(fgetc(pipe)) << endl;
_pclose(pipe);
}
One would expect to receive 256 values in serial order as so:
0,1,2,3,4,5,6,7,8,9,10,11,12,13...
But one gets
0,1,2,3,4,5,6,7,8,9,13,10,11,12,13...
There is a problem at 10, where you can see an additional 13 before it. Possibly cout wants to be helpful by adding an extra carriage return before a \n char. But it is annoying when one wants to transfer pure bytes between two processes. Yes, cout is for human readability, but is there a way to tell cout or printf to not do that? Or to use another stream which is not intended for humans to read?
Character 10 is the ASCII LF, which is treated as a line break on most platforms. On Windows specifically, the standard line break is a 13 10 (CRLF) sequence. C++ stream implementations are smart enough to know that and will convert character 10 to 13 10 on output when operating in text mode. If you don't want that to happen, you have to put the output stream into binary mode instead.
Related
This question already has answers here:
Read whole ASCII file into C++ std::string [duplicate]
(9 answers)
Closed 3 years ago.
I am trying this following code in cpp
#include <iostream>
#include <string>
void Strlength(const string& s) {
cout << s.length() << endl;
}
int main() {
string s;
cin >> s;
cout << s.length() << endl;
Strlength(s);
return 0;
}
The string which I am giving as input is 100,000 characters long and is like "xxxxxxx...xxxxabcde"(fill the ... with remaining x)
This gives me the output as
4095
4095
I am expecting the output to be 100000. what am I doing wrong?
This relates to one of the hackerrank problem (Test case 10): String Similarity
Assuming you describe the input correctly, that is it is one single "word", then the issue is not in your code. The issue must be in the environment which runs the code. It has some kind of mechanism to feed the standard input to your program. Either that has a limitation on total input length, or it has a limitation of line length. 4 kilobytes is 4096 bytes, so perhaps your input is limited by that: 4095 chars of the word plus a newline character (or terminating 0 byte of string, or whatever).
If you are running this under some kind of web interface in browser, the problem could even be, that the input field in the web page has that limitation.
If you need to dig into this, try to read char by char and see what you get, how many chars and how many newlines. Also examine cin.fail(), cin.eof(), cin.bad() and cin.good(). For the question code, you should expect failbit to be false, and eofbit might be true oe false depending on how the input was truncated.
This question already has an answer here:
feof() and fscanf() stop working after scanning byte 1b as a char. Is it because it is 'ESC' in ascii? What can I do?
(1 answer)
Closed 5 years ago.
I've got problem regarding output/input from files.
Here is my program:
#include <bits/stdc++.h>
using namespace std;
int main()
{
FILE * out;
out=fopen("tmp.txt", "w");
for(int i=0; i<256; i++)
{
fprintf(out, "%c", char(i));
}
fclose(out);
FILE * in;
in=fopen("tmp.txt", "r");
while(!feof(in))
{
char a=fgetc(in);
cout<<int(a)<<endl;
}
fclose(in);
}
and here is the output:
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
-1
Why is it stopping so quickly?
Does that mean char(26) is EOF?
How could i write to file (of any type) to overcome this problem?
What I'm looking for is a way to freely write values (of any range, can be char, int or sth else) to a file and then reading it.
Works for me *), however a few remarks:
You should not use #include <bits/stdc++.h>, that is an internal header intended for compiler use, not to be included from the client apps.
As some characters are translated (e.g. EOL) or specifically interpreted in the text (default) mode, you should open the files in binary mode.
Reading as (signed) char and converting to int will result in negative values past 127.
As fgetc already returns int, you actually do not need to do that conversion to signed char and back at all.
See here the code with the corrections.
*) Apparently as mentioned in other comments it might not work on Windows in text mode (see the point 2.).
What I'm looking for is a way to freely write values (of any range, can be char, int or sth else) to a file and then reading it.
In this case you must:
Separate the individual values with a delimiter, such as space or new-line symbol.
Read back integers rather than individual separate characters / bytes.
The easiest is to use C++ std::fstream for that. E.g.:
int main() {
{
std::ofstream out("tmp.txt");
for(int i=0; i<256; i++)
out << i << '\n';
// out destructor flushes and closes the stream.
}
{
std::ifstream in("tmp.txt");
for(int c; in >> c;)
std::cout << c << '\n';
}
}
This question already has answers here:
Why does reading a record struct fields from std::istream fail, and how can I fix it?
(9 answers)
Closed 8 years ago.
I'm trying to parse a .csv file, and I need to be able to test for a carriage return. Here is a test .csv file called sample.csv:
2
3
As you'll notice, there are two rows and one column in this file. I now write the following C++ code:
ifstream myfile (sample.csv); //Import file
char nextchar;
myfile.get(nextchar);
cout<<nextchar<<'\n';
myfile.get(nextchar);
cout<< nextchar<<" If 0, then that was not a carriage return. If 1, it was. :"<<(nextchar=='\n')<<'\n';
myfile.get(nextchar);
cout<<nextchar<<'\n';
I expect the following output:
2
If 0, then that was not a carriage return. If 1, it was. :1
3
however, I get:
2
If 0, then that was not a carriage return. If 1, it was. :0
3
How is this possible? how do I test for a carriage return??
It may be a pair of characters CR + LF. In any case you could output the code of this character yourself. Why did not you do this?
Also you could apply standard function std::isspace decalred in header <cctype>
I suggest to use standard function std::getline to read a whole line instead of using get.
There are a lot of things that can go wrong in the assumptions: OS behaviour, the text editor used to write the sample file, an undesired extra space or tab at the end of line, and the ios_base::openmode used to open the file, as well as all possible combination between those...
First instert this line to see what you actually read: is it 0x0d or 0x0a ? or somthing else ?
cout << "Char read: 0x0"<< std::hex << (int)nextchar<<"\n";
cout << "If 0 ... // Existing line
You can also replace your sample with the following. It opens the file in binary mode and display in hex the chars really in the file :
ifstream myfile ("sample.csv", ifstream::binary); //Import file
while (myfile.good() ) {
char nextchar;
myfile.get(nextchar);
if (myfile.good())
cout << "0x0"<< std::hex << (int)nextchar
<< " " << (isprint(nextchar)? nextchar:'?') <<"\n";
}
If second and third line are 0x0d and 0x0a, you'll know for sure that your text editor has put the extra CR.
Then you can remove ifstream::binary in the code above. Normally you should have, as you pointed out only 0x0a in the second line. If it's not the case, then you should investigate if the default openmode was somehow altered.
By the way, I've compiled your original code under windows and prepared the sample file using notepad , ran the programm and got... what you did expect ! Then I've redone the test with the following modification and the finally got what you got.
Good luck !
This question already has answers here:
c++ compile error: ISO C++ forbids comparison between pointer and integer
(5 answers)
Closed 5 years ago.
How to read a string one char at the time, and stop when you reach end of line? I'am using fgetc function to read from file and put chars to array (latter will change array to malloc), but can't figure out how to stop when the end of line is reached
Tried this (c is the variable with char from file):
if(c=="\0")
But it gives error that I cant compare pointer to integer
File looks like (the length of the words are unknown):
one
two
three
So here comes the questions:
1) Can I compare c with \0 as \0 is two symbols (\ and 0) or is it counted as one (same question with \n)
2) Maybe I should use \n ?
3) If suggestions above are wrong what would you suggest (note I must read string one char at the time)
(Note I am pretty new to C++(and programming it self))
You want to use single quotes:
if(c=='\0')
Double quotes (") are for strings, which are sequences of characters. Single quotes (') are for individual characters.
However, the end-of-line is represented by the newline character, which is '\n'.
Note that in both cases, the backslash is not part of the character, but just a way you represent special characters. Using backslashes you can represent various unprintable characters and also characters which would otherwise confuse the compiler.
The answer to your original question
How to read a string one char at the time, and stop when you reach end of line?
is, in C++, very simply, namely: use getline. The link shows a simple example:
#include <iostream>
#include <string>
int main () {
std::string name;
std::cout << "Please, enter your full name: ";
std::getline (std::cin,name);
std::cout << "Hello, " << name << "!\n";
return 0;
}
Do you really want to do this in C? I wouldn't! The thing is, in C, you have to allocate the memory in which to place the characters you read in? How many characters? You don't know ahead of time. If you allocate too few characters, you will have to allocate a new buffer every time to realize you reading more characters than you made room for. If you over-allocate, you are wasting space.
C is a language for low-level programming. If you are new to programming and writing simple applications for reading files line-by-line, just use C++. It does all that memory allocation for you.
Your later questions regarding "\0" and end-of-lines in general were answered by others and do apply to C as well as C++. But if you are using C, please remember that it's not just the end-of-line that matters, but memory allocation as well. And you will have to be careful not to overrun your buffer.
If you are using C function fgetc then you should check a next character whether it is equal to the new line character or to EOF. For example
unsigned int count = 0;
while ( 1 )
{
int c = fgetc( FileStream );
if ( c == EOF || c == '\n' )
{
printF( "The length of the line is %u\n", count );
count = 0;
if ( c == EOF ) break;
}
else
{
++count;
}
}
or maybe it would be better to rewrite the code using do-while loop. For example
unsigned int count = 0;
do
{
int c = fgetc( FileStream );
if ( c == EOF || c == '\n' )
{
printF( "The length of the line is %u\n", count );
count = 0;
}
else
{
++count;
}
} while ( c != EOF );
Of course you need to insert your own processing of read xgaracters. It is only an example how you could use function fgetc to read lines of a file.
But if the program is written in C++ then it would be much better if you would use std::ifstream and std::string classes and function std::getline to read a whole line.
A text file does not have \0 at the end of lines. It has \n. \n is a character, not a string, so it must be enclosed in single quotes
if (c == '\n')
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
How to make cout behave as in binary mode?
I am using C++ to print binary data to the stdout and then I redirect it to a file.
(I do not want to write directly to a file).
However, when I try to print the value '0A' I am getting '0D 0A'. (this is what I see when I copy the output to HexEdit).
From what I can figure out, '0A' is the ascii for 'new line' so cout automatically adds the '0D' which is 'carriage return'.
What I want is to print 0A alone. how can I do this?
my code:
unsigned char *buf = new unsigned char[width+1];
for (int x = 0; x < width; x++)
{
buf[x] = (unsigned char) src[x];
}
buf[width] = '\0'
cout<<buf;
I've seen this: Print new line to a text file without carriage return (CR) in windows but it does not seem to help me.
Not sure you really can use cout and the << operator without a massive hack. This is because when using << cout treats all data as text data and will perform appropriate transformations as necessary -- including adding a CR character when printing a newline on a Windows platform.
You will need to use the write method of cout, instead of using the insertion operator <<. The write method will not format your data, but is more awkward to use.
http://www.cplusplus.com/reference/iostream/ostream/write/
You can't control the end of line sequence with any of the standard output streams or files. The only way to deal with this is to freopen() the standard output stdout with an open mode of wb or wb+` to control the underlying formatting, e.g.:
FILE* out = freopen("stdout.txt", "wb", stdout);
std::cout << "hello, world\n";
If you are only using C++ streams you can also replace std::cout's stream buffer with the stream buffer of an appropriately opened std::ofstream, e.g.:
std::ofstream file("stdout.txt", std::ios_base::out);
std::streambuf* coutbuf = std::cout.rdbuf(file.rdbuf());
std::cout << "hello, world\n";
...
std::cout.rdbuf(coutbuf);
You need to restore the original stream buffer to avoid problems with uses of std::cout during destruction: at the very least the stream gets flushed at some point after main() is exited. If you can accept a memory leak, you can use a dynamically allocated std::filebuf directly.
None of the solutions above actually writes the output to the standard output, they all write to a file. I don't know how to reopen the standard output on a Windows system (on a UNIX system you'd either create a stream buffer using file descriptor 1 but on UNIX there is no need anyway because the \n doesn't get replaced in the first place). In particular, reopening the stream to fit in with output redirection is probably not possible.