Terminal behaving strangely - c

When I run a C program the terminal prompt gets erased. The program just prints out a line from a file. This always happens when I run this program . Is there some problem with my bash?
FILE* f;
...open, read a line
printf("%s", line);

There might be a carriage return (\r) character in your file which causes prompt to get erased as cursor is positioned to start of line.

To remove the problem with the '\r' character that Bug Catcher suggested just run your file through dos2unix. Should fix the problem.

Related

How to quited the git bash when Re-direct as output?

Today I have the problem about how to quit the git bash input.
The book wrote press Ctrl+D(UNIX) or Ctrl+Z(DOS) in the new line.
I try it but failed.
So I just ask the command to quit it.
Your program is written so that it quits when you enter '#' into the terminal. It cannot detect end of file because that would require a different condition. (You would have to test for EOF, and in addition declare the variable ch as int because that is the actual return value from getchar() and because EOF is usually defined as -1.)

Why does adding a \n character while appending make it possible to print out the last appended line?

I am trying to write some C code that appends a line of text to a file, and then simply display it line by line. When I open the file in append mode and add a line using fprintf, the line gets added and I can see it when I open the file with a text editor. However when I call a function to display all lines (which works fine before the new text is appended), I get all the lines until the last but excluding the new appended line.
Here is the code I'm working with. The first function just adds a new line, and the second function just reads all the lines. The read_csv() works initially when I haven't appended any lines through code and have just used a text editor to add my initial lines.
void add_record(const char* csv_filename)
{
FILE *f = fopen(csv_filename,"at");
char str="My appended line "
fprintf(f,"%s",str);
fclose(f);
}
void read_csv(const char* csv_filename)
{
FILE *f = fopen(csv_filename,"rt");
char str[MAX];
fgets(str,MAX,f);
while(!feof(f))
{ fputs(str,stdout);
fputs("\n",stdout);
fgets(str,MAX,f);
}
fclose(f);
}
Now I found two fixes to my problem but I don't exactly understand why they work.
Fix 1 : Adding an extra fgets() prints the missing appending line when I'm trying to display it, however when I use it to display my original text file it prints the last line twice..so not a good fix.
fgets(str,MAX,f)
while(!feof(f))
{ fputs(str,stdout);
fputs("\n",stdout);
fgets(str,MAX,f);
}
fgets(str,MAX,f)
Fix 2 : Adding a new line character at the along with the string appended fixes the problem perfectly and everything is smooth. All the lines get displayed when I call read_csv().
char str="My appended line "
fprintf(f,"%s\n",str)
Looking at the docs for fgets(), it says it reads until either a new line character or eof has reached(whichever occurs first), so I don't understand why my appended line get ignored by fgets().
When fgets() reaches the last line(which it skips) the situation I presume is something like this: it gets a string with " text text text eof",and it breaks out the loop skipping the print statement. But then when I use an extra fgets() outside the while loop it works. Also when I add a new line and the situation is a string like " text text text \n eof", it doesn't quit the loop and goes on to display it.
I would really appreciate if I could get some info on what is happening and why these two fixes work. I suspect it is something to do with the feof detecting an eof or some specifics about fgets but I couldn't find anything satisfactory online.
Thank you so much in advance for taking the time to read and respond.

“readline” when there is output at beginning of line

I am using the readline (version 6.3, default [non-vi] mode, Ubuntu 14.04) library from within my own program, running in a Terminal window (on a PC). There is a problem when there is previous output not terminated by newline when readline() is called.
#include <stdio.h>
#include <readline/readline.h>
void main(void)
{
// Previous output from some other part of application
// which *may* have output stuff *not* terminated with a '\n'
printf("Hello ");
fflush(stdout);
char *in = readline("OK> ");
}
So the line looks like:
Hello OK> <caret here>
If you type a small number of characters (up to 5?) and then, say, Ctrl+U (may be others) to delete your input so far it all seems well --- readline() moves the caret back to just after its own prompt, i.e. deleting 5 characters. However, try typing, say:
123456 <Ctrl+U>
Now it deletes back into the Hello, leaving just Hell on the line, followed by the caret, i.e. deleting 6+6==12. So you see:
Hello OK> 123456 <Ctrl+U>
Hell<caret here>
I need one of two possible solutions:
I have realised it depends on how many characters are typed on the line where it goes wrong. Any fix/workaround?
Alternatively, is there a readline library call I could make which would tell me what position/column the caret is at before I invoke readline()? Then at least I could recognise the fact that that I am at the end of an existing line and output a \n so as to position myself at the start of a new line first.
I think I can sort of guess that for up to 5 characters typed it does up to 5 backspaces, but over that it chooses to do something else which messes up if it did not start at beginning of line?
I see GNU Readline: how to clear the input line?. Is this the same situation? The solutions seem pretty complex. Is it not possible to ask what column you are at when starting readline(), or to tell it not to try to be so clever at deleting and stick to only deleting as many characters as have actually been typed into it?
It turns out that readline cannot recognise if it is not starting at column #1, and thereby stop itself from messing up the previous output on the line.
The only way to deal with this is to recognise the starting column ourselves, and move to the start of the next line down if the current position is not column #1. Then it will always starts from the left-most column, without outputting an unnecessary newline when it is already at column #1.
We can do this for the standard "Terminal" because it understands an ANSI escape sequence to query the current row & column of the terminal. The query is sent via characters to stdout and the response is read via characters the terminal inserts into stdin. We must put the terminal into "raw" input mode so that the response characters can be read immediately and will not be echoed.
So here is the code:
rl_prep_terminal(1); // put the terminal into "raw" mode
fputs("\033[6n", stdout); // <ESC>[6n is ANSI sequence to query terminal position
int row, col; // terminal will reply with <ESC>[<row>;<col>R
fscanf(stdin, "\033[%d;%dR", &row, &col);
rl_deprep_terminal(); // restore terminal "cooked" mode
if (col > 1) // if beyond the first column...
fputc('\n', stdout); // output '\n' to move to start of next line
in = readline(prompt); // now we can invoke readline() with our prompt

Getting a weird percent sign in printf output in terminal with C

I have this printf statement at the end of my program:
printf("%d", total_candies);
total_candies is an int, and while I expect everything to work correctly, along with the actual number, I'm getting a weird percent sign at the end.
Can anyone tell me why this is happening?
When (non-null) output from a program doesn't include a trailing newline, zsh adds that color-inverted % to indicate that and moves to the next line before printing the prompt; it's generally more convenient than bash's behavior, just starting the command prompt where the output ended.
Running PROMPT_EOL_MARK='' into the command line fixes this.
In zsh
PROMPT_SP
Attempt to preserve a partial line (i.e. a line that did not end with a newline) that would otherwise be covered up by the command prompt due to the PROMPT_CR option. This works by outputting some cursor-control characters, including a series of spaces, that should make the terminal wrap to the next line when a partial line is present (note that this is only successful if your terminal has automatic margins, which is typical).
When a partial line is preserved, by default you will see an inverse+bold character at the end of the partial line: a ‘%’ for a normal user or a ‘#’ for root. If set, the shell parameter PROMPT_EOL_MARK` can be used to customize how the end of partial lines are shown.

How to go to the previous line in a C code

If for the following code:
printf("HEllo\n"); // do not change this line.
printf("\b\bworld");
I need an output: Helloworld (In a single line). But this does not work fine. Could anyone please explain the reason? And other escape sequence if any.
There is no platform-independent control character to move back up a line. This harkens back to the days of line printers, where printf actually would print a line of text onto a sheet of paper and there was no way of retracting the paper to overwrite what had already been printed.
That said, there are libraries like ncurses that let you move the cursor around the console. They're just not part of the standard libraries.
How about simply:
printf("Helloworld");
\n is an escape sequence for a new line. Since you want everything to appear on the same line, there's no reason to specify \n.
The problem is you can't reliably move back up a line (using \b) after you've printed a new line. But if you require that there be two lines of code in your source, you can simply omit both escape sequences:
printf("HEllo");
printf("world");
If you're writing a Win32 console application, you can take advantage of the Console Screen Buffer API. The following code will move 1 line up:
printf("HEllo\n");
CONSOLE_SCREEN_BUFFER_INFO coninfo;
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
GetConsoleScreenBufferInfo(hConsole, &coninfo);
coninfo.dwCursorPosition.Y -= 1; // move up one line
coninfo.dwCursorPosition.X += 5; // move to the right the length of the word
SetConsoleCursorPosition(hConsole, coninfo.dwCursorPosition);
printf("world");
Output:
HElloworld
Remove "\n" from your first printf. It moves the cursor to a new line.
Here is the list of escape sequences.
If you can't remove "\n", then you can do make a copy of a substring without these charaters. See the following example:
const char* from = "12345678";
char *to = (char*) malloc(6);
strncpy(to, from+2, 5);
All you need is to determine the index of "\n" characters.
The backspace character, when sent to a stream (such as through the printf() family of functions), does not seek backward in the file, it is sent as-is. If you run your example, the backspace character will be output as "garbage".
If you don't want a new line, don't post a newline character.
It is because '\b' is a terminal escape code... (sans the 'escape' of course ;-)
so it only modifies what you see on the terminal. That is, the terminal adjusts its display to respond to the backspace code, even though it received everything prior to it. A file also receives everything, including the backspace code, but it is not a tty device so the file's content is not modified; it keeps everything you send to it.
If printing an extra blank is a problem, then you should code some extra logic to print the trailing blank on every output except the last.
Reference This is in reference to files but maybe same idea applies. You might want to check out this link there is a very detailed explanation that most probably answers your question.
In a console, you can't go up a line. You can clear the screen and redraw it (which simulate going up a line.) Or you can rewrite on the same line. \r will take you to the beginning of the line you just printed.
You can do it actually in a platform-independent* way, assuming that you can somehow calculate the x offset of the previous line.
int x = printf("Hello, World!\n");
gotoxy(x-1-1,gety()-1); // One for the length-offset difference and the other to skip \n
printf("\b \b");
You can avoid using that variable by directly replacing it with x.
Note: printf() returns an int (the length of the passed String (of characters)). Use it wisely :)

Resources