Related
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
Hello guys so I write this program which purpose is to open a file and read how many characters has in it and print the line with the most and the least characters.I've made it into two functions one for the biggest line and one for the smallest.The "biggest line" function works just fine but I get wrong output for the smallest one.Here is the code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <conio.h>
char f_view[150];
void ShowResults();
int leastsymbols();
int mostsymbols();
int main(){
ShowResults();
return 0;
}
int mostsymbols(){
FILE *fp;
fp=fopen(f_view, "r");
if(fp==NULL){
printf("Error\n");
exit(-1);
}
int lineNO=1;
int c;
int currCount=0;
int highestCount=0;
int highestline=0;
while ((c = getc(fp)) != EOF){
if (c == '\n') {
currCount=0;
lineNO++;
}
if (c != '\n' && c != '\t' && c!= ' ') {
currCount++;
if(currCount>highestCount){
highestCount=currCount;
if(lineNO>highestline){
highestline=lineNO;
}
}
}
}
fclose(fp);
return highestline;
}
int leastsymbols()
{
FILE *fp;
fp = fopen(f_view, "r");
if (fp == NULL)
{
printf("Could not open file \n");
exit(-1);
}
int c;
int lineNO = 1;
int currCount=0;
int leastLine=0;
int leastCount=1000;//assuming that a line in a file can not be longer
//than 1000 characters
while ((c = getc(fp)) != EOF){
if (c == '\n'){
currCount = 0;
lineNO++;
}
if (c != '\n' && c != '\t' && c!= ' ') {
currCount++;
}
if(currCount<leastCount){
leastCount=currCount;
leastLine=lineNO;
}
}
fclose(fp);
return leastLine;
}
void ShowResults()
{
FILE *fptr;
char *fix;
char c;
char openFile[1024];
printf("Type the destination to the *.c file or the file name.\n");
//the user has to enter a .C file
while(f_view[strlen(f_view) - 2] != '.' && f_view[strlen(f_view) - 1]
!= 'c')
{
fgets(f_view, 150, stdin);
fix = strchr(f_view, '\n');
if(fix != 0)
*fix = 0;
}
if((fptr = fopen(f_view, "r")) == NULL)
{
printf("Cannot open file !\n");
exit(-1);
}
int highestLine;
int lowestLine;
while (fgets(openFile, 1024, fptr))
{
highestLine=mostsymbols();
lowestLine=leastsymbols();
}
printf("Line %d has the most symbols.\n",highestLine);
printf("Line %d has the least symbols.\n",lowestLine);
fclose(fptr);
return ;
}
I fixed my program thank you.:)
while ((c = getc(fp)) != EOF){
if(c == '\n' && currCount<leastCount){
leastCount=currCount;
leastLine=lineNO;
}
if(c=='\n'){
currCount = 0;
lineNO++;
}
if (c != '\n' && c != '\t' && c!= ' ') {
currCount++;
}
}
move this check to when you go to the next line
if(currCount<leastCount){
leastCount=currCount;
leastLine=lineNO;
}
your placement is wrong because currCount is at the first iteration is still 1 or 0 depending on what is first character on the line, so it is the smallest and this is for every new line you read
I have a small problem working with dates, whereas I need to print all lines in a .txt file containing the user's current date.
Here's my code:
//My function
int search(FILE *fp, char * str)
{
FILE *fp1;
fp1 = fopen("fp1","w");
char s[10],c;
int len = strlen(str);
int i = 0;
int d;
int seek = fseek(fp, 0, 0);
c = fgetc(fp);
while (c != EOF)
{
if (c == ' ' || c == '\n')
{
s[i] = '\0';
i = 0;
if (strcmp(s, str) == 0)
{
while (c = fgetc(fp) != '\n')
{
fseek(fp, -2L, 1);
d = ftell(fp);
}
while ((c = fgetc(fp)) != '\n')
{
fputc(c, fp1);
}
}
}
else
{
s[i] = c;
i++;
}
c = fgetc(fp);
}
return 1;
}
//int main function callback
printf("\n\nTasks due today("__DATE__"): \n");
FILE *tasks = fopen("tasks.txt", "r+");
search(tasks, __DATE__);
fclose(tasks);
Any idea on how to get this working?
Thank you.
Try this:
#include <stdio.h>
#include <string.h>
int search(FILE *fp, const char *str){
FILE *fp1;
fp1 = fopen("fp1","w");
if(!fp || !fp1 || !str || !*str)
return 0;
char line[128];
while(fgets(line, sizeof line, fp)){
if(strstr(line, str)){
fputs(line, fp1);
}
}
fclose(fp1);
return 1;
}
int main(void){
printf("\n\nTasks due today(\"%s\"): \n", __DATE__);
FILE *tasks = fopen("tasks.txt", "r");
search(tasks, __DATE__);//Note that __DATE__ is at the time of compilation.
fclose(tasks);
return 0;
}
I want to write code were the user is asked to write the name of a file. Then I want to analyze the file's content for a symbol, let's say 'e'.
My problem is that I don't know how to start analyzing the file the correct way so that the content can be checked.
int main() {
char c[1000], file_name[1000];
int i;
int s = 0;
FILE *fp;
printf("Enter the name of file you wish to see\n");
gets(file_name);
if ((fp = fopen(file_name, "r")) == NULL){
printf("Error! opening file");
exit(1);
}
if (fp) {
while (fscanf(fp, "%s", c) != EOF) {
printf("%s", c);
}
fclose(fp);
for (i = 0; c[i] != '\0'; ++i) {
puts(c);
if (c[i] == 'e') {
++s;
}
}
printf("\nWhite spaces: %d", s);
_getche();
return 0;
}
}
char line[512]; /*To fetch a line from file maximum of 512 char*/
rewind(fp);
memset(line,0,sizeof(line)); /*Initialize to NULL*/
while ( fgets(line, 512, fp ) && fp !=EOF)
{
/*Suppose u want to analyze string "WELL_DONE" in this fetched line.*/
if(strstr(line,"WELL_DONE")!=NULL)
{
printf("\nFOUND KEYWOD!!\n");
}
memset(line,0,sizeof(line)); /*Initialize to null to fetch again*/
}
If its just a symbol you're looking for, or a char, you can simply use getc() :
int c;
....
if (fp) {
while ((c = getc(fp)) != EOF) {
if (c == 'e') {
// Do what you need
}
}
Or, alternatively, if it's a word you're looking for, fscanf() will do the job:
int c;
char symb[100];
char symbToFind[] = "watever"; // This is the word you're looking for
....
while ((c = fscanf(fp, %s, symb)) != EOF) {
if (strcmp(symb, symbToFind) == 0) { // strcmp will compare every word in the file
// do whatever // to symbToFind
}
}
These alternatives will allow you to search every char or string in the file, without having to save them as an array.
Following is my code to remove comments from a C program. But the comment lines don't get removed. It removes /* and */, but doesn't remove the sentence between this delimiters.
#include <stdio.h>
main(int argc, char *argv[]) {
FILE *fp, *ft;
char ch;
if (argc < 3) {
printf("No file name given");
}
fp = fopen(argv[1], "r");
ft = fopen(argv[2], "w");
if (fp == NULL)
printf("Opening error");
if (ft == NULL)
printf("Opening error");
while (1) {
ch = fgetc(fp);
if (ch == EOF)
break;
if (ch == '/') {
ch = fgetc(fp);
if (ch == '*') {
putc(' ', ft);
}
} else if (ch == '*') {
ch = fgetc(fp);
if (ch == '/') {
putc(' ', ft);
}
} else {
putc(ch, ft);
}
}
fclose(fp);
fclose(ft);
}
Please help me to remove comment lines.
There are multiple issues in your code:
the return type of main should not be omitted. Implicit int is obsolete and no longer allowed by the C Standard. The prototype should be int main(int argc, char *argv[])
if command line arguments were not passed to the program, it should exit after printing the error message, which should be output to stderr instead of stdout.
if the input file cannot be open, the program should not create the output file.
if either fopen failed, the program should stop instead of wandering into the realm of undefined behavior.
ch must have type int instead of char for the test (ch == EOF) to behave correctly.
you correctly identify the sequences /* and */ and replace them by a single , but it will actually remove all other occurrences of / and * and the subsequent character and you do not have any provisions for skipping the characters in between.
main should return 0.
Note also that your method might not identify comments correctly if the sequences /* or */ occur in single line comments or string or character constants. Furthermore, you should also handle escaped newlines (\ at the end of a line) as these may occur between the / and *, concealing the comment start or end sequences.
Here is a modified version that handles these cases:
#include <stdio.h>
/* read the next byte from the C source file, handing escaped newlines */
int getcpp(FILE *fp) {
int ch;
while ((ch = getc(fp)) == '\\') {
if ((ch = getc(fp)) != '\n') {
ungetc(ch, fp);
return '\\';
}
}
return ch;
}
/* read and write character and string constants */
int skipstr(int cch, FILE *fp, FILE *ft) {
int ch;
putc(cch, ft);
while ((ch = getcpp(fp)) != EOF) {
putc(ch, ft);
if (ch == cch)
return 0;
if (ch == '\\') {
if ((ch = getcpp(fp)) == EOF)
return EOF;
putc(ch, ft);
}
}
return EOF;
}
int main(int argc, char *argv[]) {
FILE *fp, *ft;
int ch;
if (argc < 3) {
fprintf(stderr, "Missing arguments. Need input and output filenames\n");
return 1;
}
if ((fp = fopen(argv[1], "r")) == NULL) {
fprintf(stderr, "Cannot open input file %s\n", argv[1]);
return 1;
}
if ((ft = fopen(argv[2], "w")) == NULL) {
fprintf(stderr, "Cannot open output file %s\n", argv[2]);
return 1;
}
while ((ch = getcpp(fp)) != EOF) {
if (ch == '\'' || ch == '"') {
if (skipstr(ch, fp, ft)) {
fprintf(stderr, "unterminated string or character constant\n");
break;
}
continue;
}
if (ch == '/') {
if ((ch = getcpp(fp)) == '*') {
/* multi-line comment */
int lastc = 0;
while ((ch = getcpp(fp)) != EOF) {
if (ch == '/' && lastc == '*') {
break;
}
lastc = ch;
}
if (ch == EOF) {
fprintf(stderr, "unterminated comment\n");
break;
}
ch = ' ';
} else if (ch == '/') {
/* single-line comment */
while ((ch = getcpp(fp)) != EOF && ch != '\n')
continue;
if (ch == EOF)
break;
} else {
putc('/', ft);
}
}
putc(ch, ft);
}
fclose(fp);
fclose(ft);
return 0;
}
Your code correctly identifies the comment start sequence "/" and the comment end sequence "/" and deletes them but doesn't delete what lays between them (a flag for instance should do it)
/*
* flag = 1 if comment detected
* flag = 0 otherwise
*/
if (flag == 0)
{
putc (ch, ft);
}
If you keep your code as it is, it will delete all '/' not only in comment but anywhere in the file. I can think of at least one bad consequence for this (when calling headers such as <sys/time.h>, <sys/stat.h>, <netinet/in.h>, and so on ).
Since the start and end sequences of comment are two characters wide, I would suggest that you use 2 "cursors" to read fp, as if you are reading 2 characters per loop. Hereafter an example (even though it works, for simplicity and readability reasons it doesn't handle edge cases such as non closed comment before EOF, or EOF right after a closing comment sequence).
#include <stdio.h>
int
main (int argc, char *argv[])
{
FILE *fp, *ft;
char ch, nextc;
if (argc < 3)
{
printf ("No file name given");
}
fp = fopen (argv[1], "r");
ft = fopen (argv[2], "w");
if (fp == NULL)
printf ("Opening error");
if (ft == NULL)
printf ("Opening error");
nextc = fgetc (fp);
while (nextc != EOF)
{
ch = nextc;
nextc = fgetc (fp);
if ((ch == '/') && (nextc == '*'))
{
nextc = fgetc (fp);
while ((ch != '*') && (nextc != '/')) /* unroll until the end of comment*/
{
ch = nextc;
nextc = fgetc (fp);
}
ch = fgetc (fp);
nextc = fgetc (fp);
}
putc (ch, ft);
}
fclose (fp);
fclose (ft);
return 0;
}
Hope this helps.
Your last else part is writing all characters which are not '/' and '*'.
I have changed your code below. *******Additional line ********* shows the changed parts. Try it and inform me?? good luckk...
#include<stdio.h>
main(int argc,char*argv[])
{
FILE *fp,*ft;
char ch;
int flag=0; //**********************additional line********
if(argc<3)
{
printf("No file name given");
}
fp=fopen(argv[1],"r");
ft=fopen(argv[2],"w");
if(fp==NULL)
printf("Opening error");
if(ft==NULL)
printf("Opening error");
while(1)
{
ch=fgetc(fp);
if(ch==EOF)
break;
if(ch=='/')
{
ch=fgetc(fp);
if(ch=='*')
{
flag=1; //**********************additional line********
putc(' ',ft);
}
}
else if (ch=='*')
{
ch=fgetc(fp);
if(ch=='/')
{
flag=0;//**********************additional line********
putc(' ',ft);
}
}
if(flag==0) //**********************additional line********
{
putc(ch,ft);
}
}
fclose(fp);
fclose(ft);
}
Just change the line in above code
while ((ch != '*') && (nextc != '/'))
to
while (!((ch == '*') && (nextc == '/')))
For this question most of the answers handled only multi line comment (/..../) but there may be single (//....) line comment as well.
So to handle single line comment slight modification is there in krouis 's code.
#include <stdio.h>
int main (int argc, char *argv[])
{
FILE *fp, *ft;
char ch, nextc;
if (argc < 3)
{
printf ("No file name given");
}
fp = fopen (argv[1], "r");
ft = fopen (argv[2], "w");
if (fp == NULL)
printf ("Opening error");
if (ft == NULL)
printf ("Opening error");
nextc = fgetc (fp);
while (nextc != EOF)
{
ch = nextc;
nextc = fgetc (fp);
if ((ch == '/') && (nextc == '*'))
{
ch = fgetc (fp);
nextc = fgetc (fp);
while (!((ch == '*') && (nextc == '/'))) /* unroll until the end of comment*/
{
ch = nextc;
nextc = fgetc (fp);
}
nextc = fgetc (fp);
continue;
}else if((ch=='/') && (nextc == '/')) // block to handle single line comment.
{
nextc = fgetc (fp);
while (!(nextc == '\n')){
nextc = fgetc (fp);
}
nextc = fgetc (fp);
continue;
}
putc (ch, ft);
}
fclose (fp);
fclose (ft);
return 0;
}
/* This file is to remove all comments from a c/c++ source file */
/* Modified by John Dai 2020-05-06 */
#include <stdio.h>
int main (void)
{
char *sourceFile = "D:/Temp/MyCfile.cpp"; //your source code
char *outputFile = "D:/Temp/MyCfileWoComments.cpp"; //output file
FILE *fp, *ft;
char ch, nextc;
fp = fopen (sourceFile, "r");
ft = fopen (outputFile, "w");
if (fp == NULL) {printf ("Error in opening source file\n"); return 1;}
if (ft == NULL) {printf ("Error in opening output file\n"); return 1;}
nextc = fgetc (fp);
while (nextc != EOF)
{
ch = nextc;
nextc = fgetc (fp);
if ((ch == '/') && (nextc == '/'))
{
nextc = fgetc (fp);
while (nextc != '\n') {// move to the end of line
nextc = fgetc (fp);
}
ch = nextc; //end of line character
nextc = fgetc(fp); //read 1st character from a new line
}
else if ((ch == '/') && (nextc == '*')){
{
nextc = fgetc (fp);
while (!((ch == '*') && (nextc == '/'))) {/* move to the end of comment*/
ch = nextc;
nextc = fgetc (fp);
}
ch = fgetc (fp); //read first character after the end of comment block
nextc = fgetc (fp);
}
}
putc (ch, ft);
}
fclose (fp);
fclose (ft);
return 0;
}
you can try something like this:
#include <stdio.h>
#include <string.h>
#define READ 0
#define SINGLE_LINE_COMMENT 1
#define MULTILINE_COMMENT 2
#define STRING_READ 3
#define CHAR_READ 4
int row = 1;
int col = 0;
int er_line = 0;
int er_col = 0;
void read_source(FILE *src, FILE *dst, int flag, char prev_char, int past_read)
{
if (feof(src))
{
if (flag == STRING_READ)
{
printf("Error : non-terminatig string at line :%d col :%d \n", er_line, er_col);
}
if (flag == CHAR_READ)
{
printf("Error : non-terminatig char constant at line :%d col :%d \n", er_line, er_col);
}
if (flag == MULTILINE_COMMENT)
{
printf("Error : comment reach to end of file at line :%d col :%d \n", er_line, er_col);
}
fclose(src);
fclose(dst);
return;
}
char ch = fgetc(src);
past_read++;
if (ch == '\n')
{
row++;
col = 0;
}
else
{
col++;
}
char next_ch = '\0';
switch (ch)
{
case '\n':
if (flag == SINGLE_LINE_COMMENT)
{
flag = READ;
past_read = 0;
}
else
{
if (flag == STRING_READ)
{
printf("Error : non-terminatig string at line :%d col :%d \n", er_line, er_col);
return;
}
if (flag == CHAR_READ)
{
printf("Error : non-terminatig char constant at line :%d col :%d \n", er_line, er_col);
return;
}
}
break;
case '/':
next_ch = fgetc(src);
if (next_ch == '/')
{
if (flag != STRING_READ && flag != CHAR_READ && flag != SINGLE_LINE_COMMENT && flag != MULTILINE_COMMENT)
{
flag = SINGLE_LINE_COMMENT;
er_line = row;
er_col = col;
past_read = 0;
}
}
else
{
if (next_ch == '*')
{
if (flag != STRING_READ && flag != CHAR_READ && flag != SINGLE_LINE_COMMENT && flag != MULTILINE_COMMENT)
{
flag = MULTILINE_COMMENT;
er_line = row;
er_col = col;
past_read = 0;
}
}
else
{
fseek(src, -1, SEEK_CUR);
}
}
break;
case '"':
if (prev_char != '\\')
{
if (flag == STRING_READ)
{
flag = READ;
past_read = 0;
}
else
{
if (flag != STRING_READ && flag != CHAR_READ && flag != SINGLE_LINE_COMMENT && flag != MULTILINE_COMMENT)
{
flag = STRING_READ;
er_line = row;
er_col = col;
past_read = 0;
}
}
}
break;
case '\'':
if (prev_char != '\\')
{
if (flag == CHAR_READ)
{
flag = READ;
past_read = 0;
}
else
{
if (flag != STRING_READ && flag != CHAR_READ && flag != SINGLE_LINE_COMMENT && flag != MULTILINE_COMMENT)
{
flag = CHAR_READ;
er_line = row;
er_col = col;
past_read = 0;
}
}
}
else
{
if (flag == CHAR_READ)
{
if (past_read > 2)
{
flag = READ;
past_read = 0;
}
}
}
break;
case '*':
if (flag == MULTILINE_COMMENT)
{
next_ch = fgetc(src);
if (next_ch == '/')
{
ch = '\0';
flag = READ;
past_read = 0;
}
else
{
fseek(src, -1, SEEK_CUR);
}
}
break;
}
//to work with char constant
if (flag == CHAR_READ)
{
if (ch != '\\')
{
if (prev_char != '\\')
{
if (past_read > 3)
{
printf(" Error : non-terminatig char constant at line :%d col :%d\n", er_line, er_col);
return;
}
}
}
else
{
if (past_read > 3)
{
printf(" Error : non-terminatig char constant at line :%d col :%d\n", er_line, er_col);
return;
}
}
}
if (flag != MULTILINE_COMMENT && flag != SINGLE_LINE_COMMENT && ch != '\0' && ch != EOF)
{
fputc(ch, dst);
}
read_source(src, dst, flag, ch, past_read);
return;
}
int main(int argc, char **argv)
{
FILE *fp = fopen(argv[1], "r");
FILE *fp2 = NULL;
if (fp == NULL)
{
printf("Unable to open file %s\n", argv[1]);
return 0;
}
fp2 = fopen(argv[2], "w");
if (fp2 == NULL)
{
printf("Unable to open file %s\n", argv[2]);
}
read_source(fp, fp2, READ, '\0', 0);
return 0;
}