Strange stdout behavior in C++ - c++

I want my program to display the unix windmill while processing. There's a for loop and in every iteration theres a printf function:
printf("Fetching articles (%c)\r",q);
q is one of the characters in the windmill (-\|/) depending on the iteration number.
The problem is - it seems like in 100 iterations there are only two changes in displayed line, and every iteration takes about one second to complete.
What could be the aouse for this?
Here's the whole loop with only two possible chars for the windmill:
for (int i=0;i<numb_articles;i++) {
memset(file_path,0x0,BUFF_SIZE);
url=article_urls[i];
if (rules->print!=NO_PRINT) {
url=modify_url(url,rules->printout,rules->print);
if (url=="NULL")
continue;
}
get_page(url,file_content);
if (strcmp(rules->save.data(),"NULL")!=0)
if (!check_save(rules->save,file_content,url))
continue;
at_least_one_saved=true;
numb_articles_accepted++;
encoding_list[i]=get_encoding(file_content);
title=get_title(file_content,err_msg);
if (title=="")
continue;
title_list[i]=strdup(title.data());
filename=get_filename(title);
int count=numb_fn_found(filename_list,i,filename.data());
char *tmp = new char[10];
if (count>0) {
sprintf(tmp,"(%d)",count);
filename.insert((size_t)filename.length(),tmp);
}
filename_list[i]=strdup(filename.data());
char q;
if (i%2==0)
q='|';
else q='-';
printf("Fetching articles (%c)\r",q);
ofstream output_file;
sprintf(file_path,TMP_FILE,filename.data());
strncat(file_path,".html",5);
output_file.open(file_path);
output_file << file_content;
output_file.close();
}

Flush the output after writing each line:
printf("Fetching articles (%c)\r",q);
fflush(stdout);
Without doing this, normally stdout is buffered and only dumps its output when a newline is seen, or its internal buffer fills up.

The output (console) is buffered. That is, it only writes the output to the screen when the buffer is full or a newline is written. If you want to output characters one at a time, you will need to call fflush(stdout) explicitly to flush the output buffer.

Related

What happens during the process of cin.get()?

The code is as follows, when I enter "101010^Z000", my output becomes "000". Obviously, my input is invalid after it becomes "^Z". However, why can I continue typing after typing "^Z"? According to the code, shouldn't it have jumped out of the loop and ended the program at this time? I'm curious.
int main()
{
const int num = 20;
int a[num];
int i = 0;
while((a[i]=cin.get())!=EOF)
{
a[i] = cin.get();
cout.put(a[i]);
i++;
}
cout << a;
}
like this:
And, after this I keep typing "ssss" and the program still outputs "ss" as if the loop is continuing.
Input is usually buffered. There is nothing in C++ that says it must be buffered but usually it is. What this means is that when your program is waiting for input it waits for a whole line of input. That whole line of input goes into a buffer and subsequent reads take characters from the buffer until it is empty. Then the next read will cause the program to wait again, and again it will wait for a whole line of input to be entered.
If you want unbuffered input then I've afraid there is no way to get that in standard C++. You have to use platform specific functions for that.

Is there a data structure for implementing a function equivalent to 'tail -n' command in C++?

I want to write a function equivalent to the Linux tail -n command in C++. While, I parsed over the data of that file line-by-line thereby incrementing the line count, if the file size gets really big(~gigabytes), this method will take a lot of time! Is there a better approach or a data structure to implement this function?
Here are my 2 methods:
int File::countlines()
{
int lineCount = 0;
string str;
if (file)
{
while (getline(file, str))
{
lineCount += 1;
}
}
return lineCount;
}
void File::printlines()
{
int lineCount = 0;
string line;
if (file)
{
lineCount = countlines();
file.clear();
file.seekg(ios::beg);
if (lineCount <= 10)
{
while (getline(file, line))
{
cout << line << endl;
}
}
else
{
int position = lineCount - 10;
while (position--)
{
getline(file, line);
}
while (getline(file, line))
{
cout << line << endl;
}
}
}
}
This method is time consuming if the file size increases, so I want to either replace it with another data structure, or write a more efficient code.
One of the things that is slowing down your program is reading the file twice, so you could keep the last n EOL positions (n=10 in your program) and the most convenient data structure is a circular buffer but this isn't provided by the standard library as far as I know (boost has one). It can be implemented by an std::vector with size n, with an index where a modulo of n is done after incrementing.
With that circular buffer, you can jump immediately to the lowest offset (next one if buffer is full) in the file and print the needed lines.
When I've done this, I've done a generous estimate of the maximum length of a line (e.g., one kilobyte), seeked to that distance from the end, and started reading lines into a circular buffer until the end of the file.
In nearly every case, you get more than n lines, so you just print out the contents of the circular buffer, and you're done. Note, however, that you do need to assure that you read more than n lines, not just n lines. The first line you read will usually only be a partial line, so if you read exactly n lines, the first would probably be only a partial line.
On rare occasion, you haven't gotten the required number of lines, so you seek back twice as far (or other factor of your choice), and restart. If you want to get really fancy, you can extrapolate the number of lines you'll need based on the average length of the lines you did read (but honestly, this is such a rare situation it's not worth a lot of work to optimize it).
This normally works essentially instantly, regardless of file size. I suppose (in theory) for a file with incredibly long lines, it would get slower, but if that's the case, the user has probably made a mistake, and tried to tail something that isn't a text file (which is generally useless anyway).

C++ reading multiple lines from stdin

There is a part of a code I wrote in C++:
int main(int ac, char **av)
{
std::string line;
while (std::getline(std::cin, line)) {
std::cout << "[" << line << "]\n";
}
return (0);
}
Code works properly when it comes to easy examples; it can read multiple lines (single lines in while loop) one by one and display them in terminal:
The problem appears when I try to copy paste two or more lines and print them on the screen; std::getline() blocks and is stuck, unable to read the input till the end (I can guess it's already been read and it's stored somewhere in buffer maybe?).
However, when I click enter it displays the input left, line by line, which is completely fine and desired since it - as the name points - reads one line at time.
Is it possible to unblock std::getline() somehow so it reads entire block of code?
I hope I explained it well, thanks for helping!

I don't understand buffered output and cout

I've got a really simple program that prints lines using cout and sleeps after each line. All is well and good for about 7 iterations, as the buffer is clearly not flushed at any point. After then, what I assume is only part of the buffer is flushed on every iteration.
I have a few questions about this behaviour:
If the buffer is supposedly big enough to fit ~7 lines of output, why is the buffer flushed one line at a time?
If this buffer is indeed flushed in this way, what is the advantage to this? Why isn't the whole buffer flushed at once?
Is it just a coincidence that the exact same number of characters are flushed to the output as my line length, or is the cout buffer internally flushed based on end-of-line delimiters such as '\n'?
int main(){
for(int i = 0; i < 100; ++i){
std::cout << "This is line " << i << '\n';
Sleep(1000);
}
return 0;
}
You seem to assume that the buffer will not be written until it is full. Probably what happens is that an asynchronous write is started with as little as one output byte. The empty buffer space is used to receive characters while the asynchronous write is in progress. When the current write completes, if/when there are additional characters in the buffer, a new asynchronous write is started. The process would only need to block on writing if the buffer got full.

EOF - scanf and printf

I'm tring to do a simple exercise here, but i need to understand how EOF works first.
void main()
{
char s1[1000];
while (scanf("%s", s1)!=EOF)
;
printf("%s",s1);
}
The idea is to have multiple lines in input, and display them.
The problem I have is that if I put
Hello World
This is stackoverflow
When printf is called, it only prints
stackoverflow
Why isn't it printing everything and how do I make it print?
Regards
Remove the semicolon ;:
while (scanf("%s", s1)!=EOF)
printf("%s",s1);
Note that this will still exhibit odd behavior at end of file depending on how it ends exactly. Furthermore, it splits the input into words, which are separated by spaces or new lines. You may want to simply split into lines.
So you may be better served with for instance:
while (gets(s1)!=NULL)
puts(s1);
This code fragments reads your input line by line until end-of-file.
To read everything (or as much as your buffer can hold), you can use:
char s1[1000] = "";
fread(s1, sizeof(s1) - 1, 1, stdin);
puts(s1);
However, my preferred method of reading a text file is:
using namespace std;
string line;
while (getline(cin, line))
{
cout << line << endl;
}
That is because usually I want to process a file line by line, and getline with a string ensures the line buffer is always big enough.
You probably want this:
char s1[1000][20];
int i = 0 ;
while (!feof(stdin))
fgets(s1[i++], 20, stdin) ;
int j ;
for (j = 0; j < i; j++)
printf("%s\n", s1[j]);
Here you can enter at most 1000 lines that are maximum 19 characters long.
What you have is a loop that reads words into a buffer until it reaches EOF (and does nothing with those words), followed by a printf to print the contents of the buffer. The printf is after the loop (not in it), so executes once after the loop completes. At that time, the buffer will contain the last word read, so that is what gets printed.
The EOF return test means "nothing more to be read", which isn't necessarily an end of file (might be an error condition of some kind), but in practice that distinction can be ignored. Looping until your reading function returns EOF or NULL (depends on function) is good practice.
If you want to print each word as it is read, you need to put a printf in the loop.
If you want to store the words for later processing, you need to store them somewhere. That means declaring some storage space, or allocating space on the heap, and some bookkeeping to track how much space you've used/allocated.
If you want lines rather than words, you should use fgets instead of scanf("%s". Note that fgets returns NULL rather than EOF when there's nothing more to be read.
Because it only prints the last thing that is read from the file ("stackoverflow"). This is caused by the semicolon after the end of your while(...); - this means that you are doing while(...) { /* do nothing */} - which is probably not what you wanted
Also, printf("%s",s1)!='\0'; makes no sense at all. For one thing, printf returns the number of characters printed - '\0' is the value zero written as a character constant. And of course, doing != 0 of the result without some sort of use of the comparison is pretty much pointless too.
Use fgets instead of scanf if you want to read one line at at time. scanf will stop reading when it finds a whitespace. fgets will read till the end of the line.
Use fgets(). Simple and sweet
char buf[1000];
while (fgets(buf, sizeof buf, stdin) != NULL) {
fputs(buf, stdout);
}
Here is how end-of-file works in C. The input channels are called input streams; disk files and stdin are both input streams. The "end-of-file" state is a flag that a stream has, and that flag is triggered when you try to read from a stream, but it turns out there are no more characters in the stream, and there never will be any more. (If the stream is still active but just waiting for user input for example, it is not considered to be end-of-file; read operations will block).
Streams can have other error states, so looping until "end-of-file" is set is usually wrong. If the stream does go into an error state then your loop will never exit (aka. "infinite loop").
The end-of-file state can be checked by feof. However, some input operations also can signal an error as well as, or instead of, returning the actual data they were intended to read. These functions can return the value EOF. Usually these functions return EOF in both cases: end-of-file, and stream error. This is different to feof which only returns true in the case of end-of-file.
For example, getchar() and scanf will return EOF if it was end-of-file, but also if the stream is in an error state.
So it is OK to use getchar()'s result as a loop condition, but not feof on its own.
Also, it is sometimes not OK to use scanf() != EOF as a loop condition. It's possible that there is no stream error, but just that the data you requested wasn't there. For example, if you scan for "%d" but there are letters in the stream. Instead, it's better to check for successful conversion (scanf returns the number of successful conversions it performed). Then when you exit your loop, you can go on to call feof and ferror to see whether it was due to end-of-file, or error, or just unexpected input.