Parsing a line from file [closed] - c

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 years ago.
Improve this question
I have a file with the following line:
numOfItems = 100
I want to read the line from file and initialize the attribute "numOfItems" to 100. How could I do it, i.e, deleting the unnecessary spaces and read only the values I need?
Also, I have another line which is:
num Of Items = 100
which I need to parse as error (attributes and values cannot contain spaces).
In the first case I know how to remove the spaces at the beginning, but not the intervening spaces. In second case I don't know what to do.
I thought to use strtok, but couldn't manage to get what I needed.
Please help, thanks!

Using fgets and sscanf with %s %d and %n should parse lines of the format "item = value"
#include <stdio.h>
#include <string.h>
int main( void){
char line[256] = { '\0'};
char item[50] = { '\0'};
int value = 0;
int used = 0;
printf ( "enter string as \"item = value\" or x to exit\n");
while ( ( fgets ( line, 256, stdin))) {
if ( strcmp ( line, "x\n") == 0) {
break;
}
//%49s to prevent too many characters in item[50]
//%n will report the number of characters processed by the scan
//line[used] == '\n' will succeed if the integer is followed by a newline
if ( ( ( sscanf ( line, "%49s = %d%n", item, &value, &used)) == 2) && line[used] == '\n') {
printf ( "parsed item \"%s\" value \"%d\"\n", item, value);
}
else {
printf ( "problem parsing \n\t%s\n", line);
}
printf ( "enter string as \"item = value\" or x to exit\n");
}
return 0;
}

Related

Extract a multi-digit decimal from a string in c [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed last year.
Improve this question
I have a buffer containing a null terminated string buf[100].
I am using fgets to read from a fd into the buffer in a while loop.
Here is an example string that might be read into the buffer
Sundaresan Sulochana 579 917 8024
All strings follow this convention of "last first area_code ...". I want to extract the area code as a decimal (so in this case 579). I am currently iterating through the string looking for spaces, finding the start of the area code, reading 3 characters, then converting to decimal, but I was wondering if there is a more efficient way. I tried sscanf but was getting unexpected results.
Thanks!
input_data = fdopen(in_p[0], "r");
int i, j;
while (fgets(buf, 100, input_data) != NULL) {
if (sscanf(buf, "%*s%*s%d", &new_code) == 1){
printf("code = %d\n", new_code);
}
else
{
printf("Error scanning area code\n");
}
/*
for (i=0,j=0;buf[i] != '\n'; i++){
if (buf[i] == ' '){
j++;
}
if (j == 4){
for(j=0; j<3; j++){
str_code[j] = buf[j+i+1];
}
str_code[3] = '\n';
new_code = atoi(str_code);
break;
}
}*/
User input is best done using a combination of fgets() and strtok(), IMHO. For example, if you with to read a record exactly as you described:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
printf( "last first area_code ... ? " );
fflush( stdout );
char s[1000] = {0};
fgets( s, sizeof(s), stdin );
const char * delimiters = " \t";
char * last_name = strtok( s, delimiters );
char * first_name = strtok( NULL, delimiters );
char * area_code_s = strtok( NULL, delimiters );
int area_code = area_code_s ? atoi( area_code_s ) : 0;
//...
// (Make sure to check that nothing is NULL before trying to print it.
// You should be able to do this when using a code snippet online.)
printf( "%s %s's area code is %d.\n", first_name, last_name, area_code );
}
If you are reading records, it is worth your time to make a struct:
struct person
{
char last_name[50];
char first_name[50];
int area_code;
...
};
And a function to convert a string to a struct:
bool s_to_person( char * s, struct person * p )
{
if (!s) return false;
// ...
// use strtok(), etc here. Make sure to watch out for errors, and
// return true only if nothing went wrong.
return true;
}
Which you can then use in a loop. For example, to fill an array of people:
enum { MAX_PEOPLE = 1000 };
struct person people[MAX_PEOPLE];
int npeople = 0;
char s[1000];
while ((npeople < MAX_PEOPLE)
and s_to_person( fgets( s, sizeof(s), stdin ), people+npeople ))
{
npeople += 1;
}
Make sure to keep your reference handy and avoid passing NULL values as argument to standard functions taking strings.

Input numbers from Stdin [duplicate]

This question already has an answer here:
How to use sscanf in loops?
(1 answer)
Closed 1 year ago.
I was trying to create a AVLtree using stdin input in C, the format I was trying to in put is: (7,19) (5,16) (9,13). The code I am using is
char str[1024];
int key,value;
while (fgets(str,256,stdin)!=NULL)//stop read files when reached end of the line
{
if(*str == "\n")
{
break;
}
if(sscanf(str,"(%d, %d)",&key, &value) == 2)// if the function can address both number
{
//InsertNode(AVLtree,key,value);
printf("%d, %d\n", key,value);
}
else
{
printf("cannot get correct key & Value");
exit(1)
}
Basically, I am saying that read input from stdin using "fgets" function, in (%d, %d) format. Once it reached the end of the line, then stop. But by using this code, it only allows me to type in those nodes one per line, instead of typing all of them and end with enter. Is there any way to fix this?
As you don't know how many value pairs the user will enter you have to use a loop.
After a successful sscanf you can search for a closing parenthesis ')' and start the next sscanf from the position after it.
To avoid an error message in case of additional spaces between or after the data I added code to skip whitespace and changed the format string to be more flexible.
I use a function for skipping space and checki9ng for end-of-string because I need it at two places.
Edit:
As shown in the answer to a similar question How to use sscanf in loops? you can get the offset to the next position directly from sscanf using the %n format specifier, so the strchr is not necessary. I won't change this answer here. See the other question and adapt the code accordingly.
(There are more ways to solve this problem.)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
/* skip whitespace and check for end of string */
int skip_space(char **pos)
{
while(isspace(**pos))
{
(*pos)++;
}
return (**pos == '\0');
}
int main()
{
char str[1024];
char *pos;
int key,value;
printf("enter key-value pairs of integer numbers like (a,b)(c,d): ");
while (fgets(str,sizeof(str),stdin)!=NULL)//stop read files when reached end of the line
{
pos = str;
if(skip_space(&pos))
{
break;
}
do
{
/* added spaces to format string for more flexibility */
if(sscanf(pos," (%d , %d )",&key, &value) == 2)// if the function can address both number
{
//InsertNode(AVLtree,key,value);
printf("%d, %d\n", key,value);
}
else
{
printf("cannot get correct key & Value at position %d: %s\n", (int)(pos - str), pos);
exit(1);
}
/* since scanf was successful we must have a ')' in the input, so NULL should not occur */
pos = strchr(pos, ')');
/* skip ')' */
pos++;
} while(skip_space(&pos) == 0);
}
return 0;
}
Result:
enter key-value pairs of integer numbers like (a,b)(c,d): (1,2) ( 3 , 4 ) (5,6)(7.0,8)
1, 2
3, 4
5, 6
cannot get correct key & Value at position 21: (7.0,8)
enter key-value pairs of integer numbers like (a,b)(c,d): (1,2) ( 3 , 4 ) (5,6)
1, 2
3, 4
5, 6
(7,8)
7, 8
Unrelated error: if(*str == "\n") is wrong.
If you want to check for a newline character at the beginning of the string, use
if(*str == '\n')
If you want to check if the whole string is equal to a string that consists of a single newline, use
if(strcmp(str, "\n") == 0)
or simplified
if(!strcmp(str, "\n"))

csv file visualization program [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 2 years ago.
Improve this question
I would like to write a program that will open a csv file and create its visualization in a txt file.
I mean:
input:
(this is csv file)
apple;orange;strawberry
car;warsaw;ansi
output in txt file
apple|orange|strawberry
car |warsaw| ansi
The idea is that the width of the whole column should be adjusted to the longest expression in it
output in my program
apple|orange|strawberry
|car|warsaw|ansi
|
I have too many separators, and they're not in line
My code:
#include <stdio.h>
#include <string.h>
#include <string.h>
#define MAXLINE 1000
int how_many_delimiter(char array[]);
int main(void)
{
FILE *f,*f_2;
int *size_of_column, counter, hmd, min;
char corrector[] = ";", rows[MAXLINE], *clipboard;
f = fopen("ex-5.csv", "r");
f_2 = fopen("wynik.txt", "w");
fgets(rows, MAXLINE, f);
hmd = how_many_delimiter(rows);
size_of_column = (int*)calloc(hmd,sizeof(int));
min=10;
while(fgets(rows, MAXLINE, f))
{
clipboard = strtok(rows, corrector);
counter=0;
if(strlen(clipboard)>size_of_column[counter])
{
size_of_column[counter] = strlen(clipboard);
}
while(clipboard!=NULL)
{
if(strlen(clipboard)>size_of_column[counter])
{
size_of_column[counter] = strlen(clipboard);
}
clipboard = strtok(NULL,corrector);
counter++;
}
}
fclose(f);
f = fopen("ex-5.csv", "r");
while(fgets(rows, MAXLINE, f))
{
clipboard = strtok(rows, corrector);
counter=0;
while(clipboard!=NULL)
{
fprintf(f_2,"%-*s|",size_of_column[counter], clipboard);
clipboard = strtok(NULL,corrector);
counter++;
}
}
fclose(f);
fclose(f_2);
return 0;
}
int how_many_delimiter(char array[])
{
int counter, i;
i = 0;
counter = 1;
while(array[i]!='\n'&& array[i]!=EOF)
{
if(array[i]==';') counter++;
i++;
}
return counter;
}
Steps to do this (using an alternate to the "%*s", width method):
Loop to get length of longest word in all categories
int len = strlen(longestWord);
Create format string container char formatStr[80];
Populate formatStr: sprintf(formatStr, "%s%d%s", "%", len+5, "s");
+5 is arbitrary, change as needed for space between columns.
Use formatStr in the printf() statements for each word.
So for example the longest word shown in your example is strawberry. My suggestion was to programmatically parse all of the words into buffers, and loop on them, performing strlen() on each to determine longest. Once you've found, in this case, strawberry, len will be 10, so the format specifier would be "%15s" (if you use my recommended +5). But the value 15 will be in an int variable by then (say for example int longest. Since inserting it directly into the normal format string: ( "%longests" ) will not compile, it will need to be packaged up into a format string, formatStr as shown in bullets above, and here:
sprintf(formatStr, "%s%d%s", "%", longest + 5, "s|");
( Will look like: "%s15s|" )
Once this is done, you can use the format string in the printf statements
This then:
fprintf(f_2,"%-*s|",size_of_column[counter], clipboard);
Becomes:
fprintf(f_2,formatStr, clipboard);
(either method will work.)

How would I scan a string of unknown length in c? Is there a way to do without using functions? [duplicate]

This question already has answers here:
How can I read an input string of unknown length?
(11 answers)
Closed 3 years ago.
I wanna know how would you scan a string on unknown length? Suppose I ask for someone's full name and that includes spaces too and just want to scan what the input is and print it. I read a few answers about this but all included a long function using malloc/realloc. Is there a way I could ask for the input and just print it in the main function itself?
#include <stdio.h>
int main(void)
{
char name[100][100];
int i,n;
printf("\nEnter The Limit : ");
scanf("%d", &n);
for(i=0; i<n; i++)
scanf("%s\n"),name[i]);
for(i=0; i<n; i++)
printf("\n%s",name[i]);
}
This is as far as I can think of, I can only put a limit to the number of characters you enter, is there any other better way to do it? Could I use strlen here if it's possible?
I read this question How can I read a input string on unknown length in c?
The answers here mention using a different function, I want to know if there is a simpler way to do it ? C programmers often make big programs where they ask for the name of the person including fullname? Do all of you use the large function as mentioned in the answered question or is there a simpler way?
Thanks for answering!
Use fgets for input. Unless stdin has been redirected, fgets will read your input. Because of the array sizes, fgets will read up to 99 characters or a newline.
For integers, read a line with fgets and parse with sscanf or strtol.
If fgets fails, it will return NULL.
sscanf will return the number of items that were successfully scanned. In this case 1 or 0 and can return EOF.
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
char name[100][100] = { ""};
char line[100] = "";
int i = 0;
unsigned int n = 100;
int result = 100;
do {
printf("\nEnter The Limit : ");
fflush ( stdout);
if ( ! fgets ( line, sizeof line, stdin)) {
fprintf ( stderr, "fgets EOF\n");
exit ( EXIT_FAILURE);
}
result = sscanf(line,"%u", &n);
} while ( 1 != result || n >= 100);
for(i=0; i<n; i++) {
printf("\nEnter name[%d] : ", i);
fflush ( stdout);
if ( ! fgets ( name[i], sizeof name[i], stdin)) {
fprintf ( stderr, "fgets EOF\n");
exit ( EXIT_FAILURE);
}
}
for(i=0; i<n; i++) {
printf("\n%s",name[i]);
}
return 0;
}
lets say you have a character pointer, a simple way would be to loop using a while until you find the end of the string.
This below regards scanning one name
#define MAXLENGTH 255
int n,i=0;
char* fauxString=(char*)calloc(MAXLENGTH, sizeof(char));
//Make initial allocation of max amount of characters
fgets(fauxString, MAXLENGTH, stdin);
// using fgets to get the complete line from input buffer using stdin
while (fauxString[i]!='\0'){i++;}
// finding length of the input
n=i+1;
//storing length in n
fauxString=(char*)realloc(fauxString,n*sizeof(char*));
// reallocating to size n of actual "string"
printf(fauxString);

Formatting a .csv file to print a table (C) [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
We don’t allow questions seeking recommendations for books, tools, software libraries, and more. You can edit the question so it can be answered with facts and citations.
Closed 4 years ago.
Improve this question
I have to print formatted table of csv file. I wonder if you know about any specific library or a tool that can help me with this - I just didn't find anything by googling.
this is the code and the code works fine, just have to print it like a formatted table. thanks!
void opportunity_table()
{
int i = 3;
char line[LINESIZE];
FILE* fp = fopen("opportunity_table.csv", "r");
if (!fp) {
printf("File failed to open!\n");
exit(1);
}
while (fgets(line, LINESIZE, fp)) {
while (line[i] != '\n') {
if (line[i] == ',') {
printf("%s ", "");
}
else
printf("%c", line[i]);
i++;
}
i = 0;
puts(" ");
}
}
the input I get from running this code is messy and look really bad.
Make use of the width and precision fields of the %s specifier. The width field sets a width of at least the specified characters. The precision field will print up to the specified number of characters. Works as long as width is greater than precision.
strpbrk will give a pointer to the next character in the string or NULL.
The format string "%*.*s" will right justify the printing. Use "%-*.*s" to left justify.
#include <stdio.h>
#include <string.h>
#define WIDTH 7
int main( void) {
char csv[] = "a,b,cde,fghij,i,jh\n";
char *item = csv;
char *comma = NULL;
while ( *item && ( comma = strpbrk ( item, ",\n"))) {//pointer to each comma and the newline
printf ( "%*.*s", WIDTH, comma - item, item);
item = comma + 1;//skip the comma or newline
}
printf ( "\n");
return 0;
}
If the width of the fields needs to vary, an array of widths could be used.
#include <stdio.h>
#include <string.h>
int main( void) {
char csv[4][50] = {
"a,b,cde,fghij,i,jh\n",
"i,jk,lmno,pq,rst,uvw\n",
"0,1,2,3456,78,9\n",
"x,y,z,01,2345,6789\n"
};
char *item = NULL;
char *comma = NULL;
int width[] = { 3, 4, 6, 7, 6, 5};
int field = 0;
for ( int loop = 0; loop < 4; ++loop) {
field = 0;
item = csv[loop];
while ( *item && ( comma = strpbrk ( item, ",\n"))) {//pointer to each comma and the newline
printf ( "%*.*s", width[field], comma - item, item);
item = comma + 1;//skip the comma or newline
field++;
}
printf ( "\n");
}
return 0;
}
This could be customized by reading the file twice. The number of fields and the maximum width could be determined in the first read. Read the file the second time and print using the calculated widths.

Resources