Strange behavior with fgets stdin and pipe character - c

I'm trying to read some text with fgets on stdin, but there's a strange behavior I don't understand.
Here is a simple code :
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main(int argc, char **argv) {
char chaine[30];
int i;
fgets(chaine, sizeof(chaine), stdin);
printf("%s", chaine);
for(i=0; i<strlen(chaine); i++) {
printf("%d[%c][%u]\n", i, chaine[i], chaine[i]);
}
}
And here is the output I have when I test it :
date | sasasa
date | sasasa
0[d][100]
1[a][97]
2[t][116]
3[e][101]
SPACE4[ ][32]
5[|][124]
6[?][4294967234]
7[?][4294967200]
8[s][115]
9[a][97]
10[s][115]
11[a][97]
12[s][115]
13[a][97]
14[
][10]
But it doesn't happen all the time .. The printf of the string is ok, but character by character, there's this thing that looks like overflow.
And it happens only with pipe and space characters. The space character transforms into these two ?? characters.
I'm using the macosx terminal.
Does anyone has ever seen this behavior ?
Thanks for helping,

Related

How to check if character read in through read system call is a backspace?

I have the following piece of code which reads in a character using the read system write call:
char character;
read(STDIN_FILENO, &character, 1);
How do I detect whether character is a backspace or not? Based on that, I need to delete the last character from the console output.
You can check if it's a backspace by looking for character number 8 (ASCII). It's written in C as '\b'.
However did you forget to put your terminal in RAW mode?
To change terminal to raw mode, see this answer to a different question: https://stackoverflow.com/a/13129698/14768 ; the code you want is in function changemode.
#include<iostream>
#include<string>
#include<cstdlib>
#include <windows.h>
#include <winuser.h>
using namespace std;
int main(){
string str;
getline(cin, str);
if(GetAsyncKeyState(8)) //checks to see if the input contained any backspaces
{
cout<<"Backspace was detected";
}
else{
cout<<"Backspace Not detected";
}
return 0;
}
or similarly using a character:
#include<iostream>
#include<string>
#include<cstdlib>
#include <windows.h>
#include <winuser.h>
using namespace std;
int main(){
char c;
cin.get(c);
if(GetAsyncKeyState(8)) //checks to see if the input contained any backspaces
{
cout<<"Backspace was detected";
}
else{
cout<<"Backspace Not detected";
}
return 0;
}
I now realised you are using C instead of C++ so all you do is change the libraries you are using.

Basic script in C (String display)

I'm trying to create a simple script on my server, basically I would like to sent a string and display it via system function...
#include <stdio.h>
int main()
{
char txt[100];
printf("Insert a text: ");
fgets(txt, 100, stdin);
system("echo %s"), txt;
return 0;
}
Rght now I'm not getting any string just "%s"
any idea why?
system("echo %s"), txt;
This isn't doing what you think; it's an expression which evaluates to txt. Since evaluating txt has no side effects, and since you're not capturing the result of the expression anywhere, adding , txt after the system call essentially does nothing. See this question for some information on the "comma"-operator in C.
Moreover, system doesn't support the use of printf-style format specifiers, so the %s in your string literal doesn't have any special meaning; it's just going to be echoed exactly as written, as you've seen. If you want to construct a command at runtime for use with system, you will have to do so with sprintf or similar.
The prototype to system() is:
int system(const char * command);
From man 3 system:
executes the shell command specified in command
From this we can safely assume s refers to a C-"string".
So prepare the string using for example snprintf():
char s[1024];
snprintf(s, 1024 -1, "echo %s", txt); /* -1 for the C-"string"'s 0-terminator */
Then pass it:
system(s);
Instead of system("echo %s"), txt; try this:
printf("%s", txt);
the system statement will not format the output, like printf.
suggest using:
#include <stdio.h>
#include <stdlib.h> // system()
#include <string.h> // strcpy(), strcat()
#define BUF_LEN (100)
int main()
{
char output[10+BUF_LEN] = "echo ";
char txt[BUF_LEN] = {'\0'};
printf("Insert a text: ");
fgets(txt, BUF_LEN, stdin);
strcat( output, txt );
system( output );
return 0;
}
The above code works very nicely, however;
do not include any command separators, semicolons, or other characters that would be interpreted by the shell in the input string.

C - Replacing words

My goal here is to read text from a file redirected from stdin, then replace certain argv passed words with the word "Replaced".
For example, if I run:
$ ./a.exe line < input.txt
where input.txt is "Test line one", at the end I should print "Test Replaced one."
I'm not quite sure where my code is going wrong, sometimes I get segmentation fault, and I'm also not sure how I would go about printing the newOut string, or if I even need one.
As a side note, if I was reading using fgets, what if the 59th character started "li" then as it started reading again as the 0th index for the next read command, "ne". Wouldn't that not count as one string for strstr to search?
Any help is appreciated, thanks
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char** argv) {
char fileRead[60];
char newOut[];
while (!feof(stdin)){
fgets(fileRead,60,stdin); //read file 60 characters at a time
if (strstr(fileRead,argv[1])){ // if argumentv[1] is contained in fileRead
strncpy(newOut, fileRead, strlen(argv[1])); // replace
}
}
return (0);
}
As I observed in the comments to your previous question, C — A better method for replacing:
An obvious suggestion is to read whole lines with fgets() and then search those (maybe with strstr()) to find the word to be replaced, and then print the material before the word and the replacement text before resuming the search from after the matched word in the line (so [given "test" as argv[1]] a line containing "testing, 1, 2, 3, tested!" ends up as "Replaced!ing, 1, 2, 3, Replaced!ed!".
This is a rather straight-forward implementation of the described algorithm.
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char **argv)
{
assert(argc > 1);
char fileRead[4096]; /* Show me a desktop computer where this causes trouble! */
char replace[] = "Replaced!";
size_t word_len = strlen(argv[1]);
while (fgets(fileRead, sizeof(fileRead), stdin) != 0)
{
char *start = fileRead;
char *word_at;
while ((word_at = strstr(start, argv[1])) != 0)
{
printf("%.*s%s", (int)(word_at - start), start, replace);
start = word_at + word_len;
}
printf("%s", start);
}
return (0);
}
Note that the position of the assert() makes this C99 code; place it after the definition of word_len and it becomes C89 code.

Why appear "#" added when copy chars in C

I'm creating a program in C, which receive a file and reverses each line like this:
$ cat file
Line 1
Line 2!
Line_3
$ ./reverse < file
1 eniL
!2 eniL
3_eniL
But I get an error and I don't know why.
In the program, I made a loop which:
Read a line from stdin to a string of 2048 chars.
Get the strlen from the read line and made a new string.
Copy, char by char, the characters of the string to the new string, in reverse order.
But, running the program, sometimes copy a char and other simbols (#) getting something like this:
http://i.stack.imgur.com/G8VTx.png
Some strings get # simbols depending on the length. Here, another example:
http://i.stack.imgur.com/1UKdL.png
The files are in us-ansii.
The code of the program is:
#include <stdio.h>
#include <string.h>
#include <sysexits.h>
#include <stdbool.h>
int main(int argc, char *argv[]){
char string[2048];
bool final = false;
while(!final){
fgets(string,2048,stdin); // Read line
if(feof(stdin))
final=true;
else{
int length;
length = (string[strlen(string)-1] == '\n') ? strlen(string)-1 : strlen(string);
char reverseStr[length];
// Loop
int count = length;
for(int i=0;i<length;i++){
reverseStr[i]=string[count-1];
count--;
}
printf("%s\n",reverseStr);
}
}
}
I have tried changing the loop:
for(int i=0;i<length;i++){
reverseStr[count-1]=string[i];
count--;
}
Whit pointers:
for(int i=0;i<length;i++){
char * pr = $reverseStr[count-1];
*pr=string[i];
count--;
}
# Symbol use to appear in the same position.
"Febrero" gets "orerbeF"
"Febrerol" gets "lorerbeF#"
"Febreroll" gets "llorerbe#" (lose the "F")
Here an image of the gdb:
When program is reversing second line "Febreroll"
reverseStr is "llorer" (in $12)
In the next iteration:
reverseStr is "llorerb" (in $14)
In the next iteration, program copy an "e" and more things:
reverseStr is "llorerbe\221\b#" (in $16)
GDB IMAGE IN A COMENT↓↓↓
This occurs because the code does not take care to insure there is a NUL character at the termination. The # happens to appear in the (uninitialized) buffer at the end, then presumably a random NUL is after that.
To fix this, do something like:
for(int i=0;i<length;i++){
reverseStr[i]=string[count-1];
count--;
}
reverseStr[length] = '\000'; // I added this.
You have the length stored as a separate count rather than a NUL terminator. So use the length in the format string.
printf("%*s\n", length, reverseStr);

C Linux - Not Writing Integers

I don't know why I keep getting troubles to write an integer to a file.
Here's the code:
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>
int main (int argc, char* argv[]) {
int fd, w;
int num=80;
fd=open ("file3.txt", O_CREAT|O_WRONLY, 0777);
if (fd>0) {
w=write (fd, &num, sizeof (int));
if (w==-1) {
printf ("Writing Error \n");
return EXIT_FAILURE;
}
}
close (fd);
return EXIT_SUCCESS;
}
Does anyone know what could it be?
Thanks a lot...
You're writing binary values to the file, not ascii. If you want ascii in the file, you need to sprintf it first to a char buffer, then write the char buffer. Or open your file with fopen instead of open and use fprintf.
p.s. you want close(fd) inside your if (fd > 0) { block. Also, technically the only error return of open is -1. All other values (positive, zero, negative) are success.
From your comments it is working 100% correctly: P happens to be decimal 80.
write() is outputting bytes of the integer not a decimal representation.
You might want to look at fopen and fprintf as an easy way to get what it looks like you are expecting.

Resources