C - Replacing words - c

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.

Related

How do I read from file and print one byte at a time? Then remove the spaces and puctuations. Then store the words in a character array

Code:
#include <stdio.h>
#include <ctype.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <stdlib.h>
#define WM 15
int main() {
int i=0,j=0,k=0,n, counter2, counter1, low, high, mid;
char sort, dummy, quit;
int a, GotBack, count, Got, innerCount;
bool DEBUG;
char temp[WM];
a = 0;
char* line[a][255];
char* search[a];
char* words[a];
long filelen;
char *buffer;
int buff;
FILE* Cprograms;
Cprograms = fopen("finalread.c", "r");
printf("Words in from the paragarph:");
fseek(Cprograms, 0, SEEK_END);
filelen = ftell(Cprograms);
rewind(Cprograms);
buffer = (char *)malloc((filelen+1)*sizeof(char));
for(i = 0; i < filelen; i++) {
fread(buffer+i, 1, 1, Cprograms);
}
printf("File len: %d\n", filelen);
printf("%s\n",*&buffer);
fclose(Cprograms);
return 0;
}
Output:
Words in from the paragarph:File len: 559
To be, or not to be, that is the question:
Whether 'tis nobler in the mind to suffer
The slings and arrows of outrageous fortune,
Or to take arms against a sea of troubles
And by opposing end them. To die, to sleep,
No more; and by a sleep to say we end
The heart-ache and the thousand natural shocks
That flesh is heir to: 'tis a consummation
Devoutly to be wish'd. To die, to sleep;
To sleep, perchance to dream, ay, there's the rub:
For in that sleep of death what dreams may come,
When we have shuffled off this mortal coil,
Must give us pause☻☺♥►☻☺♥ ☻☺♥ ☻←┌yç╧‼
I want the code to read only one byte at a time. Then I need the code to split the one-byte buffer into words and remove punctuation and make them lowercase and store them. Like char *words[] = { "to", "be", "or" }. I want it in a loop so each time it reads one byte does everything and goes back to start again.
For example,
if this stored in the file
"To be, or not to be, that is the question:"
I'll need the code to first read "To Be, or" which is a byte
Then print "To Be, or"
Then remover spaces and puctuations and divde them by words and make them lower case like
"to", "be", "or.
Then store them in an array.
Then goes back to read "not to be,"
Thanks in advance

C reading formatted text from file

i have a question on a C program that I'm doing. The beginning of the track ask this:
"Process P ask as argument the path of a file in which every line ust be 16 characters length (included the end of line), and every line must start with "WAIT" or "NOWAIT" followed by a command."
The example of input file is:
WAIT ls
NOWAIT who
WAIT date
I made this code for now:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#define MIN_SIZE 5
#define ROW_LEN 17
int main (int argc, char *argv[]) {
if (argc != 2) {
fprintf(stderr, "Program usage: %s file_path.\n", argv[0]);
exit(1);
}
int fd = open(argv[1], O_RDONLY);
struct stat fd_info;
if(fd < 0) {
perror("Error opening file");
exit(2);
}
fstat(fd, &fd_info);
if(fd_info.st_size <= MIN_SIZE) {
printf("Size of file '%s' is less or equal than 5 bytes.\n", argv[1]);
exit(3);
}
char buf[ROW_LEN];
buf[ROW_LEN - 1] = '\0';
while ((read(fd, buf, ROW_LEN - 1)) > 0) {
char type[ROW_LEN], cmd[ROW_LEN];
sscanf(buf, "%s %s", type, cmd);
printf("type=%s; command=%s;\n", type, cmd);
}
return 0;
}
In this way i can read good only if in the file.txt I complete every row with spaces until it reaches 15 characters for each line (else it start reading next line too). But in the file that prof gave us there aren't spaces to complete the row. So my question is, how can I read correctly from the file? I can't understand that "every line must have 16 characters included end of line".
Thanks to all, I hope I explained good the question!
Firstly with this sentence you must considerate each line as a possible input, but the input is coming from anyone so anything can append and any errors in consequences.
You start on the good way
you must consider all your file and after your line > check if your line is good
you can use getline to get your file easily, and strlen and strcmp to check if your line is conform.
Finaly the part "include end of line", that mean that all the line must have a length of 16 character with '\0', so in your file the "visible" length must be at 15 for the maximum,
for example if the maximal length is 3 included end of line :
"abc" : incorrect because it's equal to {'a', 'b', 'c' '\0'};
"ab" : correct because it's equal to {'a', 'b', '\0'};

Strange behavior with fgets stdin and pipe character

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,

What should I add to this C code to open more than 1 file?

This code searches for a set of numbers in a file; if it finds it, it displays the line where it found it. I want this code to search into more than 1 file. After it finished searching in the 1st file, it'll start searching in the second one and so on.
This is the output:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int busca(char *str, char *archNom);
void archivo(char *nomArchivo);
int main(int argc, char *argv[])
{
int result, errno;
if(argc < 3 || argc > 3)
{
archivo(argv[0]);
exit(1);
}
result = busca(argv[1], argv[2]);
You could iterate over argv, from 1 to argc - 2 (excluding the first and last elements), and then just run busca(argv[n], argv[argc - 1]) once for each item in the argv array. You'd have to keep track of the result to determine wether an error occurred, perhaps using min() or max().

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);

Resources