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
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
So i have to write a function that reads a file (.txt) and searches for a specific string, and then make it return the whole line that the string was on.
For example, one line is composed by student number, name, date of birth, address and course. I need to search for a name, and i need it to return the whole line, containing number, name, etc.
Ex :
Input : Search for student name : HUGO
Output :
61892 HUGOABC 12-02-2001 Address123 ETD
81029 HUGOBCA 09-09-2000 Address123 EAC
Here's my code :
fp = fopen("database_Alunos.txt", "r+");
if (fp == NULL) {
printf("Error! File is NULL...");
system("pause");
main();
}
else {
char nome[50];
printf("Choose name to search : ");
scanf("%[^\n]s", &nome);
/* ??? */
fclose(fp);
system("pause");
main();
fp is a FILE *fp, declared on top of main();
I need to know what kind of functions I can use in the space in the code with the question marks to make it scan for 'nome' and return the whole line
You'll need to loop through a getline using your fp, then you can use for example strstr to check if the name is present in this string. Note that you'll have to handle the case when the name is present in the address.
char *line = NULL;
size_t len = 0;
ssize_t read;
while ((read = getline(&line, &len, fp)) != -1) {
if (strstr(line, nome) != NULL) {
printf("%s\n", line);
}
}
Ok i figured it out, this is a function to read the line
int readline(char *buff, int len, FILE *fp) {
buff[0] = '\0';
buff[len - 1] = '\0';
char *tmp;
if (fgets(buff, len, fp) == NULL) {
*buff = '\0';
return 0;
}
else {
if ((tmp = strrchr(buff, '\n')) != NULL) {
*tmp = '\0';
}
}
return 1;
}
Func to read name and return lines :
scanf("%[^\n]s", fgets(nome, sizeof(nome), stdin));
char line[1024];
while (readline(line, 1024, fp)) {
char *aux = strdup(line);
char *numero = strtok(aux, "\t");
char *nomeAluno = strtok(NULL, "\t");
if (strstr(nomeAluno, nome) != NULL) {
printf("%s\n", line);
}
}
}
** 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);
}
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;
}
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++;
}