Sscanf - parsing with different delimiters - c

I want parse my string using sscanf:
char string[] = "/home/my/estf 122,323 452,323 662,343";
First element of string it's path and next are ints where comma or white characters are delimiters. This is my full code:
#include <stdio.h>
#include <stdlib.h>
int main(void) {
char string[] = "/home/my/estf 122,323 452,323 662,343";
char path[100];
int int1, int2, int3, int4, int5, int6;
sscanf(string, "%s %d[^,] %d %d[^,] %d %d[^,] %d",
path, &int1, &int2, &int3, &int4, &int5, &int6);
printf("Path:%s INT1:%d INT2:%d INT3:%d INT4:%d INT5:%d INT6:%d\n",
path, int1, int2, int3, int4, int5, int6);
return 0;
}
What it's wrong? Is it possible to extend it, to parse dynamic numbers of ints (no 6 exactly) and store it in integer array?

You can do something like this:
char a[3][16], z;
int b[8] = {0};
char x[] = "/home/my/estf 122,323 452,323 662,343", y[64];
sscanf(x, "%c %[^/ ,] %c %[^/] %c %[^/ ] %d %c %d %d %c %d %d %c %d", &z, a[0], &z, a[1], &z, a[2], &b[0], &z, &b[1], &b[2], &z, &b[3], &b[4], &z, &b[5]);
for (int i = 0; i < 3; i++) {
printf("%s ", a[i]);
}
for (int i = 0; b[i] != 0; i++) {
printf("%d ", b[i]);
}
There may be better methods to do this, but using sscanf you have do this way. You may even convert the really long sscanf line into a loop.
When using sscanf, you must consume the characters you're specifying in the negated scanset. So in case of a scanset like this: [^/] will read all the characters upto the first occurence of /. But, pointer will be still at the / in the source string. You must consume that / and continue reading ahead.
for more information on how sscanf works, look at man sscanf

It seems you want to be using something like strtok()
Here is this example slightly modified:
/* strtok example */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main ()
{
char string[] = "/home/my/estf 122,323 452,323 662,343";
char * pch;
pch = strtok (string, " ,");
while (pch != NULL)
{
pch = strtok (NULL, " ,");
if (pch)
{
int val = atoi(pch);
printf ("%d\n", val);
}
}
return 0;
}

Is it possible to extend it, to parse dynamic numbers of ints (no 6
exactly) and store it in integer array?
You can use strtol in a loop:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
char str[] = "/home/my/estf 122,323 452,323 662,343";
char path[100];
int ai[32];
char *ptr;
int n = 0;
ptr = strchr(str, ' ');
sprintf(path, "%.*s", ptr - str, str);
while (*ptr) {
ai[n++] = (int)strtol(ptr, &ptr, 10);
if (*ptr) ptr++;
}
printf("Path:%s", path);
for (int i = 0; i < n; i++) {
printf(" INT%d=%d", i + 1, ai[i]);
}
printf("\n");
return 0;
}

Related

Trouble comparing a single Char with an array of Chars

I've been getting the error: "subscripted value is neither an array nor pointer nor vector" for my code on line 14. It seems like it should be able to compare the value in the array to the char since they are both primitive data yet I can't seem to get it right:
#include <stdio.h>
#include <string.h>
char str[80];
char ch;
int cnt =0;
int suffix ( str, ch) {
int i=0;
while (strchr(str+i, ch) != NULL){
if (ch == str[i] ){
printf("\n %s \n", str+i);
cnt += 1;
}
i++;
}
return cnt;
}
int main() {
printf("\n Please type a single character and then press ENTER: \n");
ch = getchar();
printf("\n You have typed in the character \" %c \".\n", ch);
printf("\n Now please enter a string. Press ENTER to confirm: \n");
scanf("%s", str);
printf("\n The String you typed in is: %s.", str);
suffix(str, ch);
printf("The character \" %c \" appeares %d times in the string. \n", ch, cnt);
return 0;
}
The problem is that you are declaring the function like this:
int suffix ( str, ch)
{
...
}
without telling the compiler the type of str and ch. So the compiler assumes
they are int, and you cannot use [] on an int. You have to declare the
functions like this
int suffix(char *str, char ch)
{
...
}
And why are you declaring str, ch and cnt as global variables? There is
absoulutly no reason for that.
So the program should look like this:
#include <stdio.h>
#include <string.h>
// const char is even better, because you are not modifying the string
int suffix (const char *str, char ch) {
int cnt = 0;
int i=0;
while (strchr(str+i, ch) != NULL){
if (ch == str[i] ){
printf("\n %s \n", str+i);
cnt += 1;
}
i++;
}
return cnt;
}
void clean_stdin(void)
{
int ch;
while((ch = getchar()) != '\n' && ch != EOF);
}
int main() {
int ch;
int cnt;
char str[100];
printf("\n Please type a single character and then press ENTER: \n");
ch = getchar();
printf("\n You have typed in the character \" %c \".\n", ch);
clean_stdin(); // to get rid of the newline in the input buffer
// or if the user typed more than a single character
printf("\n Now please enter a string. Press ENTER to confirm: \n");
scanf("%99s", str);
printf("\n The String you typed in is: %s.", str);
cnt = suffix(str, ch);
printf("The character \" %c \" appeares %d times in the string. \n", ch, cnt);
return 0;
}

Can printf print defined strings?

Is it possible to scan a character, pass it to a char array and then if a is defined as string to print that string? Below is the code, (which gets the warning "cast to pointer from integer of different size")
Thanks in advance
char *a = "alpha";
int main()
{
char *A[80];
char ch;
printf("enter message");
scanf(" %c", &ch);
A[0] = (char *) ch;
printf("%s\t", A[0]);
return 0;
}
What you want might be something like this.
#include <stdio.h>
/* word candidate list: terminated by NULL */
const char* a[] = {
"alpha",
NULL
};
int main(void)
{
char ch;
int i;
/* read input */
printf("enter message");
if (scanf(" %c", &ch) != 1)
{
puts("read error");
return 1;
}
/* search for matching word(s) */
for (i = 0; a[i] != NULL; i++)
{
/* if the first character of the word is what is scanned, print the word */
if (a[i][0] == ch)
{
printf("%s\t", a[i]);
}
}
return 0;
}
Here's what you probably meant to write:
int main()
{
char A[80];
char ch;
printf("enter message");
scanf(" %c", &ch);
A[0] = ch;
printf("%c\t", A[0]);
return 0;
}
You didn't declare you array A right, and when you print a char (A[0]), you should use %c in printf() function.
If you wanted to print it as an string (%s modifier), you need to NULL-terminate it, which means adding \0 at the end of the string.
If you want to create a string from a char and print it using "%s" then, you need to do something like below:
char *a = "alpha";
int main()
{
char A[80] = {0};
char ch;
printf("enter message");
scanf(" %c", &ch);
A[0] = ch;
printf("%s\t", A);
return 0;
}
The mistakes in your code were:
You were declaring an array of char pointers instead of an array of
char
You were assigning a char typecasted as char *
Your print statement was incorrect due to the declaration of char
array being wrong.
Please note that I have initialized the array A to 0, so that the string is automatically null terminated.
Based on your comment, the updated code for your expected solution:
char *a = "alpha";
int main()
{
char ch;
printf("enter message");
scanf(" %c", &ch);
if (ch == 'a')
printf("%s\t", a);
return 0;
}
Try this code, I'm now on mobile phone. I haven't tested it.
int main()
{
char A[80];
char ch;
printf("enter message");
A[0] = (char)fgetc(stdin);
printf("\n%c\n", A[0]);
return 0;
}

Cut long strings into something shorter

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define N 24
void rez(char **c, char *s, int n, int ks);
void rez(char **c, char *s, int n, int ks)
{
int t = 0, j = 0;
char *p;
p = strtok(s," ");
t = t + strlen(p);
if (strlen(p)>N) *(c+j)=(char*)malloc((strlen(p)+1)*sizeof(char));
else *(c+j)=(char*)malloc((N+1)*sizeof(char));
while(p!=NULL)
{
if (t>N)
{
*(*(c+j)+t) = '\0';
t = strlen(p) + 1;
j++;
if (t>N) *(c+j)=(char*)malloc(strlen(p)+1);
else *(c+j)=(char*)malloc(N+1);
}
strcat(*(c+j), p);
c[j][t]=' ';
p = strtok(NULL, " ");
t=t+strlen(p)+1;
}
c[j][t]='\0';
for(j=0; j<ks; j++)
{
printf("\n %s", *(c+j));
}
}
int main(void)
{
FILE *fin;
int n, ks;
char s1[2048], filename[256];
char **c;
printf("Enter the file name->");
scanf("%s", filename);
fin=fopen(filename,"r");
if (!fin)
{
printf ("Error\n");
return -1;
}
while (fscanf(fin, "%[^\n]", s1)==1)
{
fscanf(fin, "%*[ \n]");
printf("\n String: %s \n", s1);
n=strlen(s1);
ks=n/(N-1)+1;
c=(char **)malloc(ks*sizeof(char*));
rez(c, s1, n, ks);
}
fclose(fin);
return 0;
}
This code should cut long strings into some shorter, but it gives "core dumped" in gcc. It doesn't exit from while in void rez().
In my mind, strtok() works incorrectly.
This is wrong:
char r[1]=" ";
because the string literal " " is TWO characters! It is both a space and a NULL-terminator (which is at the end of every string in C. But you explicitly said it should only be a 1 character array.

Count all character occurrences in a text file

The following code snippet is intended to count all the symbols met in a file after text is entered, next step is counting the occurrences of all characters (For instance 'a' met 3 times, 'b' 0 times etc.). However when I compile the loop goes infinite and the counting is always 0. My question is if it could be fixed or rewritten in another way.
char type, c, text[100]; counts[100];
int count=0, i;
while((type=getchar())!=EOF) {
fputc(type, f); count++;
}
printf("Symbols found: %d", count-1);
rewind(f);
while(fscanf(f, "%s", &text)) {
for (i = 0; i < strlen(text); i++) {
counts[(text[i])]++;
printf("The %d. character has %d occurrences.\n", i, counts[i]);
}
}
You can build your histogram as you read the input. The return value from getchar() is an int, not a char, since it has to represent EOF in addition to the 256 char values. Once the histogram has been built, you can iterate over the buckets and print them. Here, I have assumed that all 256 char values are possible, and included code to display unprintable characters in hex notation.
#include <stdio.h>
#include <ctype.h>
#include <string.h>
int main(int argc, char **argv)
{
int c;
int i;
int histogram[256];
int total;
memset(histogram, 0, sizeof(histogram));
total = 0;
while ((c = getchar()) != EOF) {
histogram[c]++;
total++;
}
printf("Symbols found: %d\n", total);
for (i = 0; i < 256; i++) {
if (histogram[i]) {
char repr[5];
sprintf(repr, isprint(i) ? "%c" : "\\x%02x", i);
printf("The '%s'. character has %d occurrences.\n", repr, histogram[i]);
}
}
return 0;
}
Your for loop scans the string with variable i being an index to the character tested, but your printf says i is a symbol accounted.
You should separate counting and printing results:
char * ptr;
while(fscanf(f, "%s", text))
for (ptr = text; * ptr != 0; ptr++)
counts[ (unsigned char)*ptr ]++;
for( i = 0; i < 256; i++)
printf("The %d. character has %d occurrences.\n", i, counts[i]);
Don't forget to declare count[ 256] and note that scanf gets text, not `&text~as a destination.

strcmp of array of strings and string

Can someone please tell me what is wrong with strcmp? I don't understand why I am getting a segmentation fault when comparing array of strings and string.
I figured out my problem just not sure how to go about fixing it. I will eventually be putting nam into strings based on my hash function. Before I do this though I want to check if my string already exists in my string array. If it does not exist I want to put it into the array. If it does exist I don't want to put it into my array. So I am guessing when I use strcmp on a non existent value I get null. Is there a good way to handle this?
char *strings[100];
char nam[100];
int g = 0;
while (fscanf(pFile, "%s %d", nam, &val) !=EOF)
{
strings[k] = nam;
printf(" string is %s .\n", strings[k]);
k++;
i = 0;
g = (int) strcmp (strings[0], nam);
printf("g is %d \n", g);
for(i = 0; i < 5; i++)
{
if(strcmp (strings[i], nam) == 0)
{
printf(" strings[i] is equal");
}
}
printf(" Bust out");
}
It also didn't like this. I figured I was getting a null on the non existent values so this would work.
for(i = 0; i < 5; i++)
{
if(strcmp (strings[i], nam) == '\0')
{
printf(" strings[i] is equal");
}
}
I dont understand how You are getting an error. This is How i tested it
#include <stdio.h>
#include <string.h>
int main()
{
char *strings[100];
char nam[100];
strcpy(nam, "ansh");
strings[1] = nam;
printf("\n%s", nam);
printf("\n%s", strings[1]);
int k = strcmp(nam, strings[1]);
printf("\n%d\n", k);
return 0;
}
OUTPUT-
ansh
ansh
0
you should malloc for nam or strings[k] to keep value,in the while loop ,when nam changes ,strings[k] will point somewhere unknown.
char *strings[100];
char nam[100];
int g = 0;
while (fscanf(pFile, "%s %d", nam, &val) !=EOF)
{
char *tmp = malloc( strlen(nam) + 1 );
strcpy( tmp , nam );
strings[k] = tmp;
printf(" string is %s .\n", strings[k]);
k++;
g = strcmp (strings[i], nam);
printf("g is %d \n", g);
}

Resources