reading a document and finding a specific word in that document - c

I have the following document:
WTPZ24 KNHC 032040
TCMEP4
TROPICAL STORM SIMON FORECAST/ADVISORY NUMBER 9
NWS NATIONAL HURRICANE CENTER MIAMI FL EP192014
2100 UTC FRI OCT 03 2014
THERE ARE NO COASTAL WATCHES OR WARNINGS IN EFFECT.
TROPICAL STORM CENTER LOCATED NEAR 18.8N 110.6W AT 03/2100Z
POSITION ACCURATE WITHIN 20 NM
REPEAT...CENTER LOCATED NEAR 18.8N 110.6W AT 03/2100Z
AT 03/1800Z CENTER WAS LOCATED NEAR 18.6N 110.1W
FORECAST VALID 04/0600Z 19.2N 112.2W
MAX WIND 65 KT...GUSTS 80 KT.
64 KT... 10NE 0SE 0SW 10NW.
50 KT... 30NE 30SE 20SW 20NW.
34 KT... 50NE 50SE 40SW 40NW.
FORECAST VALID 04/1800Z 20.0N 114.3W
MAX WIND 75 KT...GUSTS 90 KT.
64 KT... 20NE 10SE 10SW 20NW.
and I am trying to make a program in C that will read through the file and find the word string FORECASt VALID. Everytime a line has the words FORECAST VALID I want the program to print the line and "===>" before the line. For the rest of the document I just want it to simply print the line.
The final output put by the program should look like this:
REPEAT...CENTER LOCATED NEAR 18.8N 110.6W AT 03/2100Z
AT 03/1800Z CENTER WAS LOCATED NEAR 18.6N 110.1W
===>FORECAST VALID 04/0600Z 19.2N 112.2W
MAX WIND 65 KT...GUSTS 80 KT.
64 KT... 10NE 0SE 0SW 10NW.
50 KT... 30NE 30SE 20SW 20NW.
34 KT... 50NE 50SE 40SW 40NW.
===>FORECAST VALID 04/1800Z 20.0N 114.3W
MAX WIND 75 KT...GUSTS 90 KT.
64 KT... 20NE 10SE 10SW 20NW.
I do have some snippets of code that print the document verbatim without the ===> but I just need help in how to isolate out FORECAST VALID from a line so as to put the ===> in those lines:
FILE *fr; /* declare the file pointer */
main()
{
int n;
char line[800];
char buf[255];
fr = fopen ("wtnt23.knhc.201410141453", "rt"); /* open the file for reading */
while(fgets(line, 800, fr) != NULL)
{
sscanf (line, "%s", buf);
if (buf="FORECAST")
{
printf("===>%s",line);
}
else
{
printf("%s",line);
}
fclose(fr); /* close the file prior to exiting the routine */
} /*of main*/

if (buf="FORECAST") is totally wrong. it is not compare and you can't copy to char array with a =...
You just need to do like this:
while(fgets(line, 800, fr) != NULL)
{
if(0 == strncmp(line, "FORECAST VALID", strlen("FORECAST VALID")) )
{
printf("===>%s",line);
}
else
{
printf("%s",line);
}
}

I would use std::strings and iostreams rather than char arrays and FILE*.
Something a bit like:
int main()
{
std::ifstream ifs("wtnt23.knhc.201410141453");
std::string line;
while(std::getline(ifs, line)) // loop as long as getline() succeeds
{
if(line.find("FORECAST VALID") == 0) // line starts with this?
{
// output ===>
}
// output line + linefeed
}
}

Related

C - sscanf ignoring comma from csv file and reading the same piece of data twice

I am trying to read from a CSV file into struct. For some reason, the value for social security numbers is also reading the address and them the address is being read a second time into newBin.address. It looks like the sscanf is ignoring the comma that separates the socials and address when it reads the file but then does register it when it moves on reading the address. Any help is appreciated.
#include <stdio.h>
#include<string.h>
#include<stdlib.h>
#define STRSIZE 70
typedef struct BIN_DATA {
unsigned int user_number;
char name[32];
char social_security[10];
char address[32];
} BIN_DATA;
int main()
{
// Define variables.
FILE *in, *out;
char str[STRSIZE];
// New BIN.
BIN_DATA newBin;
// Open files.
in = fopen("updated.txt", "r");
// Check files.
if(in == NULL)
{
puts("Could not open file");
exit(0);
}
while(fgets(str, STRSIZE, in) != NULL)
{
memset(&newBin, '\0', sizeof(BIN_DATA));
sscanf(str, "%6u, %[^,], %[^,], %[^\n\r]", &newBin.user_number, newBin.name,\
newBin.social_security, newBin.address);
printf("%u. %s. %s. %s.\n", newBin.user_number, newBin.name,\
newBin.social_security, newBin.address);
}
return 0;
}
File being read:
289383,Estefana Lewey,591-82-1520,"9940 Ohio Drv, 85021"
930886,Burl Livermore,661-18-3839,"226 Amherst, 08330"
692777,Lannie Crisler,590-36-6612,"8143 Woods Drv, 20901"
636915,Zena Hoke,510-92-2741,"82 Roehampton St, 47905"
747793,Vicente Clevenger,233-46-1002,"9954 San Carlos St., 55016"
238335,Lidia Janes,512-92-7402,"348 Depot Ave, 29576"
885386,Claire Paladino,376-74-3432,"587 Front Ave, 32703"
760492,Leland Stillson,576-55-8588,"9793 Boston Lane, 08610"
516649,Wes Althouse,002-58-0518,"8597 Annadale Drive, 06514"
641421,Nadia Gard,048-14-6428,"218 George Street, 29150"
As mentioned in the comments, the social_security member does not allocate enough space to hold the data you're reading. It needs to be at least 12 to hold the SSN as written with a terminator at the end.
As for the format string you use with sscanf(), it's nearly correct. However, you'll want to bound the maximum string length to match what you have storage for, so for example with name of 32 you should limit it to 31 characters saving one at the end for the terminator.
I changed the social_security field to char social_security[12]; and then changed the format string to sscanf to be the following:
"%6u, %31[^,], %11[^,], %31[^\n\r]"
I was able to run the modified code with the sample input file to get the output you described. You can try it too at the link:
Runnable code

Unexpected Output - Storing into 2D array in c

I am reading data from a number of files, each containing a list of words. I am trying to display the number of words in each file, but I am running into issues. For example, when I run my code, I receive the output as shown below.
Almost every amount is correctly displayed with the exception of two files, each containing word counts in the thousands. Every other file only has three digits worth of words, and they seem just fine.
I can only guess what this problem could be (not enough space allocated somewhere?) and I do not know how to solve it. I apologize if this is all poorly worded. My brain is fried and I am struggling. Any help would be appreciated.
I've tried to keep my example code as brief as possible. I've cut out a lot of error checking and other tasks related to the full program. I've also added comments where I can. Thanks.
StopWords.c
#include <stdio.h>
#include <stdlib.h>
#include <dirent.h>
#include <stddef.h>
#include <string.h>
typedef struct
{
char stopwords[2000][60];
int wordcount;
} LangData;
typedef struct
{
int languageCount;
LangData languages[];
} AllData;
main(int argc, char **argv)
{
//Initialize data structures and open path directory
int langCount = 0;
DIR *d;
struct dirent *ep;
d = opendir(argv[1]);
//Count the number of language files in the directory
while(readdir(d))
langCount++;
//Account for "." and ".." in directory
//langCount = langCount - 2 THIS MAKES SENSE RIGHT?
langCount = langCount + 1; //The program crashes if I don't do this, which doesn't make sense to me.
//Allocate space in AllData for languageCount
AllData *data = malloc(sizeof(AllData) + sizeof(LangData)*langCount); //Unsure? Seems to work.
//Reset the directory in preparation for reading data
rewinddir(d);
//Copy all words into respective arrays.
char word[60];
int i = 0;
int k = 0;
int j = 0;
while((ep = readdir(d)) != NULL) //Probably could've used for loops to make this cleaner. Oh well.
{
if (!strcmp(ep->d_name, ".") || !strcmp(ep->d_name, ".."))
{
//Filtering "." and ".."
}
else
{
FILE *entry;
//Get string for path (i should make this a function)
char fullpath[100];
strcpy(fullpath, path);
strcat(fullpath, "\\");
strcat(fullpath, ep->d_name);
entry = fopen(fullpath, "r");
//Read all words from file
while(fgets(word, 60, entry) != NULL)
{
j = 0;
//Store each word one character at a time (better way?)
while(word[j] != '\0') //Check for end of word
{
data->languages[i].stopwords[k][j] = word[j];
j++; //Move onto next character
}
k++; //Move onto next word
data->languages[i].wordcount++;
}
//Display number of words in file
printf("%d\n", data->languages[i].wordcount);
i++; Increment index in preparation for next language file.
fclose(entry);
}
}
}
Output
256 //czech.txt: Correct
101 //danish.txt: Correct
101 //dutch.txt: Correct
547 //english.txt: Correct
1835363006 //finnish.txt: Should be 1337. Of course it's 1337.
436 //french.txt: Correct
576 //german.txt: Correct
737 //hungarian.txt: Correct
683853 //icelandic.txt: Should be 1000.
399 //italian.txt: Correct
172 //norwegian.txt: Correct
269 //polish.txt: Correct
437 //portugese.txt: Correct
282 //romanian.txt: Correct
472 //spanish.txt: Correct
386 //swedish.txt: Correct
209 //turkish.txt: Correct
Do the files have more than 2000 words? You have only allocated space for 2000 words so once your program tries to copy over word 2001 it will be doing it outside of the memory allocated for that array, possibly into the space allocated for "wordcount".
Also I want to point out that fgets returns a string to the end of the line or at most n characters (60 in your case), whichever comes first. This will work find if there is only one word per line in the files you are reading from, otherwise will have to locate spaces within the string and count words from there.
If you are simply trying to get a word count, then there is no need to store all the words in an array in the first place. Assuming one word per line, the following should work just as well:
char word[60];
while(fgets(word, 60, entry) != NULL)
{
data->languages[i].wordcount++;
}
fgets reference- http://www.cplusplus.com/reference/cstdio/
Update
I took another look and you might want to try allocating data as follows:
typedef struct
{
char stopwords[2000][60];
int wordcount;
} LangData;
typedef struct
{
int languageCount;
LangData *languages;
} AllData;
AllData *data = malloc(sizeof(AllData));
data->languages = malloc(sizeof(LangData)*langCount);
This way memory is being specifically allocated for the languages array.
I agree that langCount = langCount - 2 makes sense. What error are you getting?

sscanf statement stops the program

#include <stdio.h>
#include <stdlib.h>
struct urunler {
int kod;
char Ad[16];
int stok;
float fiyat;
};
void urunTara(struct urunler* inputs,int *amount);
int main()
{
struct urunler Urun[50];
int amount = 0;
urunTara(Urun,&amount);
}
void urunTara(struct urunler *inputs,int *amount){
char Temp[150];
FILE *fPtr;
fPtr = fopen("urunler.txt","r");
if(fPtr == NULL){
printf("File not found!");
} else {
while(!feof(fPtr)){
fgets(Temp,100,fPtr);
sscanf(Temp,"%d %s %d %f",&(inputs[*amount].kod),inputs[*amount].Ad,&(inputs[*amount].stok),&(inputs[*amount].fiyat));
*amount++;
}
}
};
I am relatively new to C, and just started learning about structs. The text file contains these:
25 televizyon 1000 150.25
40 video 500 25.45
50 plazma 75 2300.50
76 dvd 20000 90.00
85 supurge 700 110.75
90 buzluk 250 10.00
95 teyp 1250 8.99
The problem i have here is with the sscanf. When i do all these inside the main function, it works great. However when i try to do it in the function urunTara something goes wrong with the sscanf statement and the program stops working. I successfully passed values to &(inputs[*amount].kod) and other adresses by using scanf. But can't understand what's the problem with this sscanf statement.
*amount++;
is similar to
*(amount++);
which means dereference amount and then increment amount to the element after that. Which is not correct.
Change *amount++; to (*amount)++;, which will increment the dereferenced value.
Refer this and this for more details

C Linux fscanf not reading all of line

I'm working with some code written by someone else to scan key value string pairs from a config file. The code is:
void readProfile(char * profileName) {
FILE *f;
int i=0;
f = fopen(profileName, "r");
if (NULL != f) {
while (fscanf(f, "%s%s", &pvtProperties[i].key[0],
&pvtProperties[i].value[0]) == 2) {
i++;
}
fclose(f);
}
numberOfProperties = i;
setCurrentProfileName(profileName);
}
However when reading this plaintext config file below, it has a problem with the 4th line:, the value is truncated to "https://dev.xxxx.com:58443/services/PvtTransferSer". Each line of the config file is separated by \r\n. From that point on the reading of the rest of the file is messed up, values becoming keys etc. Why is this happening? The keys and values are char arrays of 80 chars each.
Config file:
PASSWORD xxxx
REMOTE_UPDATES_ENABLE 1
REMOTE_DIAGNOSTICS_ENABLE 1
PVT_TRANSFER_WS_ADDRESS https://www.xxxx.com:58443/services/PvtTransferService
PVT_DIAGNOSTIC_WS_ADDRESS https://www.xxxx.com:58443/services/PvtDiagnosticService
PVT_UPDATE_WS_ADDRESS https://www.xxxx.com:58443/services/PvtUpdateService
PVT_ADJUSTMENT_WS_ADDRESS https://www.xxxx.com:58443/services/PvtAdjustmentService
DAILY_RESTART_ENABLE 1
HOUR_PAST_MIDNIGHT_FOR_RESTART 7
MAX_RESTART_RANDOMIZATION_SECONDS 30
MINIMUM_UPTIME_SECONDS_BETWEEN_RESTARTS 7200
CLEAR_CACHE_ON_RESTART_ENABLE 0
MINIMUM_SECONDS_BETWEEN_REMOTE_UPDATE_CHECKS 3600
SECONDS_BETWEEN_CONTROLLER_CONFIGURATION_CHECKS 300
CONNECTIVITY_LOSS_DETECTION_ENABLE 1
SMART_COMM_ENABLE 1
TIME_SYNC_ENABLE 1
FACTORY_RESET_ENABLE 1
CM_POLL_PROTOCOL http
You can solve your phase issue by using fgets to pull a line in at a time from the file; then sscanf to parse that line buffer for each record.

Editing a line in a text file using temp file C

I am trying to edit a line in a textfile but i have an unexpected behavior while i am editing the file. What i want to do is adjust a specific line (points : 100) of a text that looks like. In the function i pass arguments by value the new coins to be adjusted and the offset of the file with ftell->user_point. What i get as an output is weird. I try to copy the rest of the file to a temp,with an edited line, and then copy it back to the original file from the point that i copied to temp.(thats the user_point offset with ftell).
Here is the original fie with entries like that:
...
_______________________________________
nickname : geo
password : cuvctq
Name : george
Surname : papas
points : 100
participated :
past draws : 0
Chosen No. :
future draws : 0
Registered : Sun Feb 05 19:23:50 2012
...
What i get after 2nd edit run is:
...
_______________________________________
nickname : geo
password : cuvctq
Name : george
Surname : papaspoints : 98
participated :
past draws : 0
Chosen No. :
future draws : 0
Registered : Sun Feb 05 19:23:50 2012
...
At the end of the text i get one extra \n after i edit the
file whch is something i dont want :/
and so further edit will spoil the text...
I also get an EXTRA \n at the end of the line which, at least what i think so, is due to "r+" mode which is something that i also dont want...
void coins_adjust(int coins_new,int user_point)
{
int lines,i,ln_point_copy;
char buffer[50],buff_copied[50];
FILE *lottary,*temp;
memset(buff_copied,'\0',sizeof(char)*50);
lottary=fopen("customers.txt","r");
temp=fopen("temp.txt","w");
fseek(lottary,user_point,SEEK_SET);
for (lines=0;lines<5;lines++)
{
memset(buffer,'\0',sizeof(char)*50);
if (lines==5)
ln_point_copy=ftell(lottary); //from TEMP to CUSTOMERS
fgets (buffer ,50 , lottary);
}
coins_new+=atoi(buffer+15);
strncpy(buff_copied,buffer,15); //copy 15 chars and fill with null
memset(buffer,'\0',sizeof(char)*50);
itoa (coins_new,buffer,10); //fix the new line to be entered
strcat(buff_copied,buffer); //the edited line is as it is supposed
strcat(buff_copied,"\n"); //to be with \n at the end.
puts(buff_copied);
printf("%s",buff_copied);fflush(stdout);
fprintf(temp,"%s",buff_copied);
for(i=getc(lottary); i!=EOF; i=getc(lottary)) //copy to temp
{
putc(i, temp);
}
fclose(lottary);
fclose(temp);
temp=fopen("temp.txt","r");
lottary=fopen("customers.txt","r+");
fseek(lottary,ln_point_copy,SEEK_SET);
for(i=getc(temp); i!=EOF; i=getc(temp)) //copy until eof
{
putc(i, lottary);
}
fclose(lottary);fclose(temp);
}
I have debugged the program and everything seems to work at least on what values are passed to the arrays where i store the line chars but i cant see why it ignores the \n of the previous line when i try to copy it back to the original... There seems to be a \r char that i cant get rid of while i copy back to the original...
Thanks in advance.
I was more thinking about something like this:
void change_points(int new_points)
{
FILE *input = fopen("customers.txt", "r");
FILE *output = fopen("temp.txt", "w");
char buffer[256];
while (fgets(buffer, sizeof(buffer), input))
{
/* Look for the correct line */
/* Can also use e.g. "if (strncmp(buffer, "points", 6) == 0)"
* if it's at the start of the line
*/
if (strstr(buffer, "points") != NULL)
{
int old_points;
sscanf(buffer, "%*s : %d ", &old_points);
/* Format how you like it */
fprintf(output, "%-13s: %d\n", "points", new_points + old_points);
}
else
fputs(buffer, output);
}
fclose(output);
fclose(input);
/* The file "temp.txt" now contains the modifeed text */
/* Copy either using "fgets"/"fputs", or using "fread"/"fwrite" */
input = fopen("temp.txt", "r");
output = fopen("customers.txt", "w");
while (fgets(buffer, sizeof(buffer), input))
fputs(buffer, output);
fclose(output);
fclose(input);
}
It's shorter, simpler, maybe more effective (looping over line-by-line instead of char-by-char), and the line you are looking for can be anywhere in the file without you knowing its exact position.

Resources