Printing multiple strings with printf in C [duplicate] - c

I am trying to read in a file, find the string "myprop" and after "myprop" will be an "=" sign then a number. I need to print out just that number as a string, getting rid of blank spaces and comments. I am able to locate the "myprop" string and then I believe I should be using fscanf but I am having trouble with that.
const char *get_filename_property()
{
const char *filename = "myfile.properties";
const char *propkey = "myprop";
char buffer[100], *buffPtr, lastChar, value[50];
int line_num=1, i=0;
FILE *fp;
fp=fopen("myfile.properties", "r");
if (fp == NULL)
perror("Error opening file\n\n");
while(fgets(buffer, 100, fp) != NULL)
{
if((strstr(buffer, propkey)) != NULL)
{
printf("Myprop found on line: %d\n", line_num);
printf("\n%s\n", buffer);
}
line_num++;
}
if (fp)
fclose(fp);
}
int main(int argc, char *argv[])
{
get_filename_property();
system("pause");
return(0);
}

You can add sscanf in the moment when you find the mypop string in the file. Add the following line in your while loop:
sscanf(buf,"%*[^=]= %[^\n]",value);
"%*[^=]": This means that scanf capte all characters befor the = and ignore it
" %[^\n]": This means that you are capting all characters after the = till the end of your buffer string (even the space characters). only the space characters in the beggining of the value string will not capted
add it in this way
while(fgets(buffer, 100, fp) != NULL)
{
if((strstr(buffer, propkey)) != NULL)
{
printf("Myprop found on line: %d\n", line_num);
printf("\n%s\n", buffer);
sscanf(buf,"%*[^=]= %[^\n]",value);
printf("\nvalue is %s\n", value);
break;
}
line_num++;
}

Related

fprintf places in odd value when processing char value

I am writing what should be a simple program, but I'm having an odd issue with fprintf I have not been able to solve.
I am reading a small CSV text file and writing those values to a separate file containing only the numeric values.
My CSV file looks like this.
000,001,002,
003,004,005,
006,007,008,
009,010,011,
255,255,255
There is a comma between each value and a return at the end of each line.
The code I am using is
#include <stdio.h>
#include <string.h>
int main(int argc, char ** argv) {
FILE * inputFile;
FILE * outFile;
char * filename;
int records = 0;
char line[15];
char * sp;
char appendString[] = ".hex";
printf("useage: dec2hex inputFile.txt\n");
// Check if a filename has been specified in the command
if (argc < 2) {
printf("Missing Filename\n");
return (1);
} else {
filename = argv[1];
printf("Read in Filename : %s\n", filename);
}
// Open file in read-only mode
inputFile = fopen(filename, "r");
if (inputFile == NULL) {
printf("Hey! Failed to open the file\n");
return (1);
}
strcat(filename, appendString);
printf("write out filename : %s\n", filename);
outFile = fopen(filename, "w");
while (fgets(line, 15, inputFile) != NULL) {
sp = strtok(line, ",");
char Y_pos = atoi(sp);
sp = strtok(NULL, ",");
char X_pos = atoi(sp);
sp = strtok(NULL, ",");
char OType = atoi(sp);
//print to file
fprintf(outFile, "%c", Y_pos);
fprintf(outFile, "%c", X_pos);
fprintf(outFile, "%c", OType);
records++;
}
fprintf(outFile, '\0');
printf("records = %d\n", records);
fclose(inputFile);
fclose(outFile);
return (0);
}
This will write to a file ..hex
The output I'm expecting should be
000102030405060708090a0bffffff
However what I'm seeing is an odd value inserted $D0.
I'm expecting $0A which does happen afterwards. I have tried some other values in my CSV (from 0 to 50) and this for now seems to be the only value that is random.
The reason I'm using %c in my fprintf is that I only need values from 0-255.
My first question, is why the odd value when processing 010?
How can this be corrected?
I'm using the TCC compiler 0.9.26, but have gotten similar results when using VS.
Thanks
However what I'm seeing is an odd value inserted $D0 $0D.
File was opening in text mode and when writing a code 10 ('\n'), incurred a "\n" to "\r\n" translation on OP's machine.
Instead open the file in binary mode.
// outFile = fopen(filename, "w");
outFile = fopen(filename, "wb");
Note: Other code short-comings exist.
you do not this strtok and atoi magic or binary mode opening magic
int main(void)
{
char line[1000];
while (fgets(line, 100, stdin) != NULL)
{
int X,Y,O;
if(sscanf(line, "%d,%d,%d,", &Y, &X, &O) != 3) { /* error handling*/ }
else
{
printf("%02x ", Y);
printf("%02x ", X);
printf("%02x ", O);
}
}
}
https://godbolt.org/z/vvKGzdcvd

Using strtok only works if I put the delimiter after the last item

So I am trying to open and read files based on stdinput. I've used strtok to parse the input so that the user can input multiple files. I've set the delimiter to space.
int main(const int argc, const char *argv[]){
if (argc == 1) {
char str[100];
const char delim[2] = " ";
printf("Enter a filename:\n");
fgets(str, 100, stdin);
char *ptr = strtok(str, delim);
while (ptr != NULL){
FILE *fp = fopen(ptr, "r");
if ((fp == NULL)) {
fprintf(stderr, "failed to open %s\n", ptr);
}
else{
printf("Opening file: %s\n", ptr);
char c;
while ((c = fgetc(fp)) != EOF){
if (c != ' '){
putchar(c);
}
if (c == ' ') {
printf("\n");
}
}
fclose(fp);
}
ptr = strtok(NULL, delim);
}
return 0;
}
If I input "example.txt example2.txt", it will read example.txt, and then say failed to open example2.txt. However, if I input "example.txt example2.txt " (notice the extra space), it will read both of them correctly, but it will say "failed to open" with no file name at the end. Also, reading one file by itself results in "failed to open". Any ideas?
fgets() includes the newline in the string. Since you didn't put newline in your delimiter string, the second filename is being returned as "example2.txt\n", and that filename doesn't exist.
Change your delimiter to include newline:
const char delim[] = " \n";

Strcmp not comparing strings from argv

** Updated 26/10 -> First of all thank you all for you help, I am getting closer now, I need more work and studying but I really appreciate you are helping me a lot :-)
Still don't know why the first "rain" word in the input.txt file is not getting the positive output from strcmp, and from the cmd I can see the "<" bracket don't appear except for the LAST line which is the line that works.
Also checked the highlighted response from Removing trailing newline character from fgets() input
and even if I change the code to the following:
while( fgets (line, sizeof line, fp)!=NULL ) {
/* remove \n from at the end of the str buffer*/
char * pos;
/*
if ((pos = strchr(line, '\n')) != NULL)
*pos = '\0';
*/
line[strcspn(line, "\n")] = 0;
I get the same result as if I use the if block instead. Maybe I'm getting extra \0 which might be the case. Anyone has a link where I can read about the delimiters I just used, or a nice reference of a debugger, etc. ... which I will have a look as soon as I come here? Thank you so much in advance!
read5.c version: Now from that input.txt file, it had an extra space on the last "rain" word, I removed the space, and it was able to find and get that last word compare as a true result, running in the strcmp if block. but that was the only string that was a true positive result from that if block.
on the cmd I can see:
$./read5 input.txt rain output.txt sun
>Maria
>rain
>manel
>Bla bla
<rain>
Found it! rain
On the output.txt it becomes:
Maria
rain
manel
Bla bla
sun
read5.c
#include <stdio.h>
#include <string.h>
/**
* Compile program:
* gcc read3.c -o read3
*
*/
int main (int argc, char **argv) {
FILE *fp, *fo;
char *compare, *replace;
char line[246];
if (argc <= 4){
printf(">Missing arguments on the command line.\n");
printf(">Be sure you run the program as\n\"./read3 input.txt compare outout.txt replace\"\n\n");
}
/* opening file for reading */
fp = fopen(argv[1] , "r");
if(fp == NULL){
perror("Error opening input file");
return 1;
}
compare = argv[2];
fo = fopen(argv[3], "w");
if(fo == NULL){
perror("Error opening output file");
return 1; //TODO check if: return 1 because it was expected, right?
}
replace = argv[4];
/*
printf(); made to test version 2
//printf("We are going to compare %s\n", compare);
//printf("We are going to replace it with %s\n", replace);
*/
while( fgets (line, sizeof line, fp)!=NULL ) {
/* remove \n from at the end of the str buffer*/
char * pos;
if ((pos = strchr(line, '\n')) != NULL)
*pos = '\0';
/* print str enclosed in <> so we can see what str actually contains */
//printf("Inside the loop, got the string: %s\n", line);
//printing the strings with defined delimiters
printf("<%s>\n", line);
if(strcmp(compare, line) == 0){
printf("Found it! %s \n", line);
fprintf(fo, "%s\n", replace);
}
else{
fprintf(fo, "%s\n", line);
}
}
fclose(fp);
fclose(fo);
return 0;
}
First question with no edits: 25/10
I need to make a program that is run like this:
./read2 input.txt rain output.txt sun
It reads the input.txt, searches for rain string and if finds it, replaces it with sun string and outputs all the text from input.txt with the replacements to the output.txt.
But with the code that I have so far, the strcmp is not comparing the strings I want, maybe it has the extra space that I get on the command line, I don't know... for now what is doing is copying everything from input.txt to output.txt... It's running the else block always...
Read2.c:
#include <stdio.h>
#include <string.h>
int main(int argc, char **argv) {
FILE *fp, *fo;
char str[60];
//char* token;
/* opening file for reading */
fp = fopen(argv[1], "r");
char *compare = argv[2];
fo = fopen(argv[3], "w+");
char *replace = argv[4];
if (fp == NULL) {
perror("Error opening file");
return(-1);
}
//printf("We are going to compare %s\n", compare);
//printf("We are going to replace it with %s\n", replace);
while (fgets(str, 60, fp) != NULL) {
/* writing content to stdout */
//Take the \n out
//token = strtok(str, "\n");
printf("Inside the loop, got the string: %s\n", str);
if (strcmp(compare, str) == 0) {
//puts(str);
printf("Found it! %s \n", str);
fprintf(fo, "%s", replace);
} else {
fprintf(fo, "%s", str);
}
}
fclose(fp);
return(0);
}
input.txt:
Maria
rain
manel
Bla bla
rain
Ouput.txt becomes exactly as input.txt and before it was empty, so the code is working, except the if block that tests with strcmp.
The problem is the \n at the end of the str buffer. fgets adds the \n at end end of the line it reads, you need to get rid of it before comparing.
This is what you need:
while (fgets(str, 60, fp) != NULL) {
/* remove \n from at the end of the str buffer*/
char *pos;
if ((pos = strchr(str, '\n')) != NULL)
*pos = '\0';
/* print str enclosed in <> so we can see what str actually contains */
printf("Inside the loop, got the string: <%s>\n", str);
if (strcmp(compare, str) == 0) {
printf("Found it! %s\n", str);
fprintf(fo, "%s\n", replace);
}
else {
fprintf(fo, "%s\n", str);
}
}
Look at the comments in the code for explanations.
read.c
#include <stdio.h>
#include <string.h>
/**
* How to compile program:
* gcc read.c -o read
*
* How to run the program:
* .> ./read input.txt rainy output.txt sunny
* (On Windows MinGW compiler, simply:
* .> read input.txt rainy output.txt sunny - without ./)
*
*/
int main (int argc, char **argv) {
FILE *fp, *fo;
char *compare, *replace;
char line[246];
if (argc <= 4){
printf(">Missing arguments on the command line.\n");
printf(">Be sure you run the program as\n\"./read input.txt compare outout.txt replace\"\n\n");
}
/* Opening files for reading */
fp = fopen(argv[1] , "r");
if(fp == NULL){
perror("Error opening input file");
return 1;
}
compare = argv[2];
fo = fopen(argv[3], "w");
if(fo == NULL){
perror("Error opening output file");
return 1;
}
replace = argv[4];
while( fgets (line, (sizeof line), fp)!=NULL ) {
line[strcspn(line, "\n")] = 0;
if(strcmp(compare, line) == 0){
printf("Found it! %s \n", line);
fprintf(fo, "%s\n", replace);
}
else{
fprintf(fo, "%s\n", line);
}
}
fclose(fp);
fclose(fo);
return 0;
}
/*
Important info
strcspn ::
Locate first occurrence of character in string,
after locating the first occurrence of \n, replaces it by 0.
Sources::
https://stackoverflow.com/questions/2693776/removing-trailing-newline-character-from-fgets-input/28462221#28462221
Used to debug:
.>printf("1st: Reads input.txt, removes '\\n' from fgets, and prints it \n");
.>printf("2nd: Compares each line with 'rainy' \n");
.>printf("<%s>\n", line);
*/
input.txt
cloudy
rainy
chilly
rainy
rainy
Your approach fails because the lines read from the input file contain a trailing newline '\n' that makes the comparison return non zero.
You can strip the newline before comparing with the search string.
Note that there are other problems:
you should verify that enough command line arguments have been passed by testing argc > 4.
there is no need to open the output file in update mode "w+", "w" is simpler and better.
60 bytes is a bit small for the line array, limiting the longest line handled correctly to 58 bytes.
Here is an improved version:
#include <stdio.h>
#include <string.h>
int main(int argc, char **argv) {
FILE *fp, *fo;
char *compare, *replace;
char line[256];
if (argc <= 4) {
printf("missing command line arguments\n");
return 1;
}
fp = fopen(argv[1], "r");
if (fp == NULL) {
perror("Error opening input file");
return 1;
}
compare = argv[2];
fo = fopen(argv[3], "w");
if (fo == NULL) {
perror("Error opening output file");
return 1;
}
replace = argv[4];
while (fgets(line, sizeof line, fp) != NULL) {
line[strcspn(line, "\n")] = '\0';
if (strcmp(line, compare) == 0) {
printf("fount it!);
fprintf(fo, "%s\n", replace);
} else {
fprintf(fo, "%s\n", line);
}
}
fclose(fp);
fclose(fo);
return 0;
}
Note that long lines will be broken into chunks that fit in the line array, so there may be false positives with the above naive approach.
You can remove this limitation completely with this inner loop:
int c;
int pos = 0;
int cmplen = strlen(compare);
for (;;) {
c = getc(fp);
if (c == '\n' || c == EOF) {
if (pos == cmplen) {
fprintf(fo, "%s", replace);
} else
if (pos > 0) {
fprintf(fo, "%*s", pos, compare);
}
pos = 0;
if (c == EOF)
break;
} else {
if (pos >= 0) {
if (compare[pos] == (char)c) {
pos++;
continue;
}
if (pos > 0) {
fprintf(fo, "%*s", pos, compare);
}
pos = -1;
}
}
putc(c, fo);
}

How to search for specific lines that starts with a string in a file

I need help with this little program I am trying to make.
There is .txt file:
namas house
katinas cat
suo dog
skaicius number
I want to find a line which begins with specific word and then prints second word of that line.
For example, user enters word katinas. Program looks through file, finds line that begins with katinas and finally prints.
What I have so far:
int main()
{
char word;
printf("Enter your word: ");
scanf("%s", &word);
FILE *fp;
fp = fopen("data.txt", "r+");
char buffer[256];
while (fgets(buffer, sizeof buffer, fp) != NULL && atoi(buffer) != word)
;
if (feof(fp))
{
printf(&buffer);
}
fclose(fp);
return 0;
}
Thank you.
There were several mistakes in the code as pointed out elsewhere. This answer will find whole words so for example "suo" but not "su".
#include<stdio.h>
#include<string.h>
int main()
{
char word[256]; // adequate string space (not single char)
char buffer[256];
char *sptr;
FILE *fp;
int found = 0;
printf("Enter your word: ");
scanf("%s", word); // requires a string pointer (note no &)
fp = fopen("data.txt", "r"); // removed "+"
if (fp) {
while (fgets(buffer, sizeof buffer, fp) != NULL) {
sptr = strtok(buffer, " \t\r\n");
if (sptr && strcmp(sptr, word) == 0) {
sptr = strtok(NULL, " \t\r\n");
if (sptr) {
printf("%s\n", sptr);
found = 1;
break;
}
}
}
fclose(fp);
}
if (!found)
printf ("%s not found\n", word);
return 0;
}
You could use a simple logic, just like using a 'for' to search for the word and right after you find the specific word that you want, continue with the 'for' until find a blank space (use ' ' to determinete the end and the beginning of a word) then print out all the letters until find the next blank ' '. This should work just fine.
char word; is a single char which can't store lines; should be an array in order to read a line.
atoi(buffer) != word you are comparing an int (returned by atoi()) with a pointer(array name gets converted into a pointer here). I really don't see the purpose of this.
You don't need to check if end of file has been reached. You just loop through the file line-by-line and check for your string.
Calling printf without format specifier is not safe and you are also passing char (*)[256] whereas printf expects a const char*.
You should also error checking on fopen().
Use a standard prototype for main() such as: int main(void)
After correcting all these, the code would be simplified to:
#include<stdio.h>
#include<string.h>
int main(void)
{
char word[256] = {0};
char buffer[256] = {0};
FILE *fp;
printf("Enter your word: ");
scanf("%s", word);
fp = fopen("data.txt", "r+");
if (!fp) { /* error */}
while ( fgets(buffer, sizeof buffer, fp) )
{
if( strstr(buffer, word) == buffer )
printf("Found: %s\n", buffer);
}
return 0;
}
There's no library function to find if a string "starts with" in C. I am using strstr to achieve that. If there's a match and it's equal to the starting address of the buffer, then it starts with word. Because strstr returns to a pointer to the first match.
#include <stdio.h>
int main(void){
char buffer[256];
char word[256], second_word[256];
char format[256];
FILE *fp;
printf("Enter your word: ");
scanf("%255[A-Za-z]", word);
sprintf(format, "%s %%255s", word);
fp = fopen("data.txt", "r");
while (fgets(buffer, sizeof buffer, fp) != NULL) {
if (sscanf(buffer, format, second_word) == 1) {
printf("%s\n", second_word);
break;//continue;?
}
}
fclose(fp);
return 0;
}

how to print a value after a specific string

I am trying to read in a file, find the string "myprop" and after "myprop" will be an "=" sign then a number. I need to print out just that number as a string, getting rid of blank spaces and comments. I am able to locate the "myprop" string and then I believe I should be using fscanf but I am having trouble with that.
const char *get_filename_property()
{
const char *filename = "myfile.properties";
const char *propkey = "myprop";
char buffer[100], *buffPtr, lastChar, value[50];
int line_num=1, i=0;
FILE *fp;
fp=fopen("myfile.properties", "r");
if (fp == NULL)
perror("Error opening file\n\n");
while(fgets(buffer, 100, fp) != NULL)
{
if((strstr(buffer, propkey)) != NULL)
{
printf("Myprop found on line: %d\n", line_num);
printf("\n%s\n", buffer);
}
line_num++;
}
if (fp)
fclose(fp);
}
int main(int argc, char *argv[])
{
get_filename_property();
system("pause");
return(0);
}
You can add sscanf in the moment when you find the mypop string in the file. Add the following line in your while loop:
sscanf(buf,"%*[^=]= %[^\n]",value);
"%*[^=]": This means that scanf capte all characters befor the = and ignore it
" %[^\n]": This means that you are capting all characters after the = till the end of your buffer string (even the space characters). only the space characters in the beggining of the value string will not capted
add it in this way
while(fgets(buffer, 100, fp) != NULL)
{
if((strstr(buffer, propkey)) != NULL)
{
printf("Myprop found on line: %d\n", line_num);
printf("\n%s\n", buffer);
sscanf(buf,"%*[^=]= %[^\n]",value);
printf("\nvalue is %s\n", value);
break;
}
line_num++;
}

Resources