Related
I need to load strings from file into a struct array.
CORRECT OUTPUT:
4
Sarajevo,345123
Tuzla,123456
Mostar,101010
Banja Luka,234987
MY OUTPUT:
1
Sarajevo 345123
Tuzla 123456
Mostar 101010
Banja Luka 234987,544366964
Code:
#include <stdio.h>
#include <string.h>
struct City {
char name[31];
int number_of_citizen;
};
int load(struct City cities[100], int n) {
FILE *fp = fopen("cities.txt", "r");
int i = 0;
while (fscanf(fp, "%[^,]s %d\n", cities[i].name, &cities[i].number_of_citizen)) {
i++;
if (i == n)break;
if (feof(fp))break;
}
fclose(fp);
return i;
}
int main() {
int i, number_of_cities;
struct City cities[10];
FILE* fp = fopen("cities.txt", "w");
fputs("Sarajevo 345123", fp); fputc(10, fp);
fputs("Tuzla 123456", fp); fputc(10, fp);
fputs("Mostar 101010", fp); fputc(10, fp);
fputs("Banja Luka 234987", fp);
fclose(fp);
number_of_cities = load(cities, 10);
printf("%d\n", number_of_cities);
for (i = 0; i < number_of_cities; i++)
printf("%s,%d\n", cities[i].name, cities[i].number_of_citizen);
return 0;
}
Could you explain me how to fix this? Why my program only loaded 1 city?
The fscanf() conversion string is incorrect: instead of "%[^,]s %d\n" you should use:
while (i < n && fscanf(fp, "%30[^,],%d",
cities[i].name,
&cities[i].number_of_citizen) == 2) {
i++;
}
Or better:
#include <errno.h>
#include <stdio.h>
#include <string.h>
int load(struct City cities[], int n) {
char buf[200];
int i = 0;
char ch[2];
FILE *fp = fopen("cities.txt", "r");
if (fp == NULL) {
fprintf(stderr, "cannot open %s: %s\n", "cities.txt",
strerror(errno));
return -1;
}
while (i < n && fgets(buf, sizeof buf, fp)) {
if (sscanf(buf, "%30[^,],%d%1[\n]",
cities[i].name,
&cities[i].number_of_citizen, ch) == 3) {
i++;
} else {
fprintf(stderr, "invalid record: %s\n", buf);
}
}
fclose(fp);
return i;
}
Also change your main function to output commas between the city names and population counts:
int main() {
int i, number_of_cities;
struct City cities[10];
FILE *fp = fopen("cities.txt", "w");
if (fp) {
fputs("Sarajevo,345123\n", fp);
fputs("Tuzla,123456\n", fp);
fputs("Mostar,101010\n", fp);
fputs("Banja Luka,234987\n", fp);
fclose(fp);
}
number_of_cities = load(cities, 10);
printf("%d\n", number_of_cities);
for (i = 0; i < number_of_cities; i++)
printf("%s,%d\n", cities[i].name, cities[i].number_of_citizen);
return 0;
}
EDIT: since there are no commas in the database file, you must use a different parsing approach:
#include <errno.h>
#include <stdio.h>
#include <string.h>
int load(struct City cities[], int n) {
char buf[200];
int i = 0;
FILE *fp = fopen("cities.txt", "r");
if (fp == NULL) {
fprintf(stderr, "cannot open %s: %s\n", "cities.txt",
strerror(errno));
return -1;
}
while (i < n && fgets(buf, sizeof buf, fp)) {
/* locate the last space */
char *p = strrchr(buf, ' ');
if (p != NULL) {
/* convert it to a comma */
*p = ',';
/* convert the modified line */
if (sscanf(buf, "%30[^,],%d",
cities[i].name,
&cities[i].number_of_citizen) == 2) {
i++;
continue;
}
}
fprintf(stderr, "invalid record: %s", buf);
}
fclose(fp);
return i;
}
This is a program to remove particular lines in a file. It copies the lines which are needed and prints it in another file in the same directory. I'm not getting any errors except for warnings such as incompatible pointer type [-Wincompatible-pointer-types]. When I run the code I also get the prtintf statement but when entered input Segmentation fault (core dumped). Is it related to the warnings or is it something else ?
code
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<stdbool.h>
#include <ctype.h>
char *name_find(char *buf[], char *name[]) {
const char *p = NULL;
size_t len = strlen(name);
if (len > 0) {
for (p = buf ; (p = strstr(p, name)) != NULL; p++) {
if (p == buf || !isalnum((unsigned char)p[-1])) {
if (!isalnum((unsigned char)p[len]))
break; /* we have a match! */
p += len; /* next match is at least len+1 bytes away */
}
}
}
return p;
}
int main()
{
char name[25];
char buf[100];
setenv("PFILE","/home/ashwin/Desktop/FILE/",1);
char ori_path[100],new_path[100];
if (!getenv("PFILE")){
}
else{
strcpy(ori_path, getenv("PFILE"));
strcpy(new_path, getenv("PFILE"));
strcat(ori_path, "shadow");
strcat(new_path, "shadow1");
}
bool success=false;
printf("Enter the command\n ");
printf("userdel ");
FILE *fold = fopen(ori_path, "r"); // old file
FILE *fnew = fopen(new_path, "w"); // new temp file
fgets(name,25,stdin);
for(int i = 0; i < strlen(name); i++)
{
if(name[i] == '\n')
{
name[i] = '\0';
break;
}
}
while (fgets(buf, 100, fold)) {
// read lines until error or EOF
if (!name_find(buf, name)) {
fprintf(fnew, "%s", buf);
success=true;
}
}
if(success){
printf("Success !!!\n");
}
return 0;
}
char *name_find(char *buf[], char *name[])
You use char *buf[], which means buf is an array of pointers to char, not a pointer to char. Use char* buf instead. Same goes for name.
Additionally:
FILE *fold = fopen(ori_path, "r"); // old file
FILE *fnew = fopen(new_path, "w"); // new temp file
You should check if the opening of the streams to the files were successful by checking the returned pointers for a null pointer:
FILE *fold = fopen(ori_path, "r"); // old file
if(!fold)
{
fputs("Error at opening fold!", stderr);
exit(1);
}
FILE *fnew = fopen(new_path, "w"); // new temp file
if(!fnew)
{
fputs("Error at opening fnew!", stderr);
exit(1);
}
Try this code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <ctype.h>
char *name_find(char *buf, char *name) {
const char *p = NULL;
size_t len = strlen(name);
if (len > 0) {
for (p = buf ; (p = strstr(p, name)) != NULL; p++) {
if (p == buf || !isalnum((unsigned char)p[-1])) {
if (!isalnum((unsigned char)p[len]))
break; /* we have a match! */
p += len; /* next match is at least len+1 bytes away */
}
}
}
return p;
}
int main (void)
{
char name[25];
char buf[100];
setenv("PFILE","/home/ashwin/Desktop/FILE/",1);
char ori_path[100],new_path[100];
if (!getenv("PFILE")){
}
else{
strcpy(ori_path, getenv("PFILE"));
strcpy(new_path, getenv("PFILE"));
strcat(ori_path, "shadow");
strcat(new_path, "shadow1");
}
bool success=false;
printf("Enter the command\n ");
printf("userdel ");
FILE *fold = fopen(ori_path, "r"); // old file
if(!fold)
{
fputs("Error at opening fold!", stderr);
exit(1);
}
FILE *fnew = fopen(new_path, "w"); // new temp file
if(!fnew)
{
fputs("Error at opening fnew!", stderr);
exit(1);
}
fgets(name,25,stdin);
for(unsigned int i = 0; i < strlen(name); i++)
{
if(name[i] == '\n')
{
name[i] = '\0';
break;
}
}
while (fgets(buf, 100, fold)) {
// read lines until error or EOF
if (!name_find(buf, name)) {
fprintf(fnew, "%s", buf);
success=true;
}
}
if(success){
printf("Success !!!\n");
}
return 0;
}
I have csv file with below format :
name,birthmonth,country,hobby
jack,jan,england,soccer
roben,july,germany,soccer
emma,dec,china,tennis
yannick,sep,france,music
alex,nov,england,cricket
thomas,apr,germany,tennis
mike,oct,netherlands,cycling
michelle,feb,france,poetry
yui,mar,japan,coding
feng,jun,china,reading
I want to parse this file using C, and put all the lines with same country name in a consecutive manner i.e shown below:
name,birthmonth,country,hobby
jack,jan,england,soccer
alex,nov,england,cricket
roben,july,germany,soccer
thomas,apr,germany,tennis
emma,dec,china,tennis
feng,jun,china,reading
yannick,sep,france,music
michelle,feb,france,poetry
mike,oct,netherlands,cycling
yui,mar,japan,coding
So far, I have tried this code below, however not able to match things properly and proceed further:
#include<stdio.h>
#include<stdlib.h>
#include<ctype.h>
#include<fcntl.h>
#include<string.h>
int main (int argc, char **argv) {
//int line;
char line[200];
char *inputFile = argv[1];
FILE *input_csv_file;
char a,b,c,d,e;
input_csv_file = fopen(inputFile, "rt");
if(input_csv_file ==0) {
printf("Can not open input file \n");
}
else {
//while((line = fgetc(input_csv_file)) != EOF) {
while(fgets(line, sizeof line, input_csv_file) != NULL) {
printf ("line = %s\n", line);
if(sscanf(line, "%s,%s,%s,%s,%s", a,b,c,d,e)) {
//if(sscanf(line, "%[^,], %[^,], %[^,], %[^,], %[^,]", a,b,c,d,e)) {
printf("d=%s\n",d);
}
}
}
return 0;
}
I am a newbie in C/C++. Any help would be much appreciated
Thanks.
I could write the code to get the required output. Below is the code:
#include<stdio.h>
#include<stdlib.h>
#include<ctype.h>
#include<fcntl.h>
#include<string.h>
int main(int argc, char ** argv)
{
struct filedata {
char nation[8];
char content[50];
};
char line[100];
char *inputFile = argv[1];
FILE *input_csv_file;
int iter = 0, c;
char * tok;
int count = 0;
char ch;
char country[] = "country";
char header_line[50];
input_csv_file = fopen(inputFile, "rt");
//count line numbers of the input csv
for(ch = getc(input_csv_file); ch!= EOF; ch=getc(input_csv_file))
if(ch == '\n')
count = count + 1;
fclose(input_csv_file);
count = count -1;
struct filedata * record[count];
input_csv_file = fopen(inputFile, "rt");
if(input_csv_file == 0)
{
printf("Can not open input file\n");
} else
{
while(fgets(line, sizeof line, input_csv_file) != NULL)
{
//printf("-- line = %s\n", line);
int s_line = sizeof line;
char dup_line[s_line];
strcpy(dup_line, line);
int h = 0;
int s_token;
tok = strtok(line, ",");
while(tok != NULL)
{
h++;
if(h == 3)
{
s_token = sizeof tok;
break;
}
tok = strtok(NULL, ",");
}
// skipping the line having column headers
if(compare_col(tok, country) == 0) {
strcpy(header_line, dup_line);
continue;
}
iter++;
c = iter - 1;
record[c] = (struct filedata*)malloc(sizeof(struct filedata));
strcpy(record[c]->nation, tok);
strcpy(record[c]->content, dup_line);
} //while
struct filedata * temp;
FILE * fptr;
fptr = fopen("nation_csv.txt", "w");
if(fptr == NULL)
{
printf("Error in opening the file to write\n");
exit(1);
}
// sorting the arr of struct nation wise
for(iter=1; iter < count; iter++)
for(c =0 ; c < count -1; c++) {
if(strcmp(record[c]->nation, record[c+1]->nation) > 0) {
temp = record[c];
record[c] = record[c+1];
record[c+1] = temp;
}
}
for(iter=0; iter < count; ++iter)
{
if(iter == 0) {
fprintf(fptr, "%s", header_line);
continue;
}
fprintf(fptr, "%s", record[iter]->content);
}
fclose(fptr);
}
fclose(input_csv_file);
}
int compare_col(char a[], char b[] )
{
int c = 0;
while(a[c] == b[c]) {
if(a[c] == '\0' || b[c] == '\0')
break;
c++;
}
if(a[c] == '\0' && b[c] == '\0')
return 0;
else
return -1;
}
Thanks for all your inputs. Any further inputs to make it better are much appreciated.
Thanks
I am trying to write a code that simulates an Anti-Virus scan, it scans 5 specific files and then creates a file named AntiVirusLog.txt. In this file it writes the results, for example PSY.avi INFECTED. An infected file is a file that contains the string in the file youtubesign.
My problem is when I try to print in the results to the file AntiVirusLog.txt it does not print anything and leaves the file blank.
My code:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<dirent.h>
#define BUZZ_SIZE 1024
int fast_scan(char *fname, char *str, FILE *fs);
int slow_scan(char *fname, char *str, FILE *fs);
int main(int argc, char *argv[])
{
char name[100];
char choice[5];
char buff[BUZZ_SIZE];
FILE *f7, *f2;
struct dirent *de;
DIR *dr = opendir(argv[1]);
if (dr == NULL) // opendir returns NULL if couldn't open directory
{
printf("Could not open current directory");
return 0;
}
f2 = fopen(argv[2], "rb");
f7 = fopen("AntiVirusLog.txt", "wt");
printf("Welcome to Amnon's Anti-Virus program\n which scan would you like to choose?:\n");
printf("Fast: check only the first and the last 20% of the file\n Slow: Checks the entire file\n");
printf("Enter fast for a fast scan and slow for a slow scan\n");
scanf("%s", choice);
if ((strcmp(choice, "slow"))==0)
{
while ((de = readdir(dr)) != NULL)
{
strcpy(name, argv[1]);
strcat(name, de->d_name);
if((fgets(buff, BUZZ_SIZE, f2)) != NULL)
{
slow_scan(name, buff, f7);
}
}
}
if ((strcmp(choice, "fast")) == 0)
{
while ((de = readdir(dr)) != NULL)
{
strcpy(name, argv[1]);
strcat(name, de->d_name);
if ((fgets(buff, BUZZ_SIZE, f2)) != NULL)
{
fast_scan(name, buff, f7);
}
}
}
printf("The scan was made successfuly, check the file AntiVirusLog.txt to see the results\n");
closedir(dr);
fclose(f2);
fclose(f7);
system("PAUSE");
return (0);
}
int slow_scan(char *fname, char *str, FILE *fs)
{
int findres = 0;
FILE *fp;
char temp[BUZZ_SIZE];
if ((fopen_s(&fp, fname, "rb")) != NULL)
{
return(-1);
}
while ((fgets(temp, BUZZ_SIZE, fp)) != NULL)
{
if ((strstr(temp, str)) != NULL)
{
fprintf(fs, "%s INFECTED\n", fname);
findres++;
}
}
if (findres==0)
{
fprintf(fs, "%s NOT INFECTED\n", fname);
}
fclose(fp);
return(0);
}
int fast_scan(char *fname, char *str, FILE *fs)
{
int findres=0;
int i, j, len, partlen;
FILE *fp;
if ((fopen_s(&fp, fname, "rb")) != NULL)
{
return(-1);
}
fseek(fp, 0, SEEK_END);
len = ftell(fp);
partlen = (len * 20) / 100;
char *temp=malloc(partlen);
while ((fgets(temp, BUZZ_SIZE, fp)) != NULL)
{
for (i = 0; i < partlen; i++)
{
if (temp[i]=str[i])
{
findres++;
}
if (temp[i] != str[i])
{
i = partlen + 1;
}
if (findres == partlen)
{
fprintf(fs, "%s INFECTED\n", fname);
i = partlen + 1;
}
}
for (j = len - partlen; j < len; j++)
{
if (temp[j] = str[j])
{
findres++;
}
if (temp[j] != str[j])
{
j = partlen + 1;
}
if (findres == partlen)
{
fprintf(fs, "%s INFECTED\n", fname);
j = partlen + 1;
}
}
}
if (findres!= partlen)
{
fprintf(fs, "%s NOT INFECTED\n", fname);
}
fclose(fp);
return(0);
}
There are primarily two major issues with your code
Point 1: In your code, for the series of calls like
search_sign(argv[1], buff, f7);
you're using buff uninitialized. The buff is then passed as the second parameter of search_sign(), (to be accepted as str) which is again used as the search string in strstr().
As buff is an automatic local variable, the initial content (value) is garbage (indeterminate) and hence , when used as the search key in strstr(), will invoke undefined behaviour.
Point 2: That said, as my previous comment, you should always be checking the success of fopen() call(s) before using the returned file pointer any further.
I have used some of the advices listen and found some fixes of my own and now it works perfectly! the updated code looks like this:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define BUZZ_SIZE 1024
int search_sign(char *fname, char *str, FILE *fs);
int main(int argc, char *argv[])
{
char buff[BUZZ_SIZE];
FILE *f,*f7;
f7 = fopen("AntiVirusLog.txt", "wt");
f = fopen(argv[1], "rb");
if ((fgets(buff, BUZZ_SIZE, f)) != NULL)
{
search_sign(argv[2], buff, f7);
search_sign(argv[3], buff, f7);
search_sign(argv[4], buff, f7);
search_sign(argv[5], buff, f7);
search_sign(argv[6], buff, f7);
}
printf("The scan was made successfuly, check the file AntiVirusLog.txt to see the results\n");
fclose(f);
fclose(f7);
system("PAUSE");
return (0);
}
int search_sign(char *fname, char *str, FILE *fs)
{
int findres = 0;
FILE *fp;
char temp[BUZZ_SIZE];
if ((fopen_s(&fp, fname, "rb")) != NULL)
{
return(-1);
}
while ((fgets(temp, BUZZ_SIZE, fp)) != NULL)
{
if ((strstr(temp, str)) != NULL)
{
fprintf(fs, "%s INFECTED\n", fname);
findres++;
}
}
if (findres==0)
{
fprintf(fs, "%s NOT INFECTED\n", fname);
}
fclose(fp);
return(0);
}
I want to write a program which print all numbers found in a file and then add them up. I have two problems:
How to add up the numbers I've printed?
Why in output_file do I have so many commas:
Here's my code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define CHUNK 12
char *getWord(FILE *infile);
void clean(char *dirty);
char *getWord(FILE *infile)
{
char *word, *word2;
int length, cursor, c;
word = (char*)malloc(sizeof(char)*CHUNK);
if(word == NULL) return NULL;
length = CHUNK;
cursor = 0;
while(!isspace(c = getc(infile)) && !feof(infile))
{
word[cursor] = c;
cursor++;
if(cursor >= length)
{
length += CHUNK;
word2 = (char*)realloc(word, cursor);
if(word2 == NULL)
{
free(word2);
return NULL;
}
else
{
word = word2;
}
}
}
word[cursor] = '\0';
return word;
}
void clean(char *dirty)
{
int i = 0, j = 0;
char *temp;
temp = strdup(dirty);
while(i < strlen(temp))
{
if(isdigit(temp[i]))
{
dirty[j] = temp[i];
j++;
}
i++;
}
dirty[j] = '\0';
free(temp);
}
int main(int argc, char *argv[])
{
char *word;
FILE *infile, *outfile;
if(argc != 3)
{
printf("Missing argument!\n");
exit(1);
}
infile = fopen(argv[1], "r");
if(infile != NULL)
{
outfile = fopen(argv[2], "w");
if(outfile == NULL)
{
printf("Error, cannot open the outfile!\n");
abort();
}
else
{
while(!feof(infile))
{
word = getWord(infile);
if(word == NULL)
{
free(word);
abort();
}
clean(word);
fputs(word, outfile);
fputs(",", outfile);
free(word);
}
}
}
else
{
printf("Error, cannot open the outfile!\n");
abort();
}
fclose(infile);
fclose(outfile);
return 0;
}
infile:
You are getting , because of this -
fputs(",", outfile);
It is related in structure to the echo unix command. The core of the program could be simplified to something along the following lines:
int c, need_comma = 0;
while ((c = fgetc(infile)) != EOF) {
if (isdigit(c)) {
fputc(c, outfile);
need_comma = 1;
}
else {
if (need_comma == 1) {
fputc(',', outfile);
need_comma = 0;
}
}
}
this removes the need for getWord and clean functions.
This is just the printing part. the intermediate file is in CSV format,
which is structured and easy to parse and add the numbers (and print the
result to another file).