I have string having multiple words separated with commas like
char str[]="K&R,c89,c99,c11";
I am trying to read the first 2 words into a separate character arrays using sscanf().
sscanf(str, "%[^,] s%[^,]s", str1, str2);
I intended sscanf() to scan through str till reaching a ,, store it to str1, continue scanning till another , and store into str2.
But value is being stored only into str1 while str2 seem to be having garbage.
I tried removing the space between the %[^,]ss if that was of any significance but it made no difference on the output.
What am I doing wrong? Or is this not possible for multiple words?
I've heard of doing something like this with strtok() but I was wondering if sscanf() could be used for this.
Duh.. It took me a while to see it. Get rid of the s in your format string. The character class [...] takes the place of s and by putting s in there, you are forcing sscanf to look for a literal s in str, e.g.
#include <stdio.h>
#define MAX 8
int main (void) {
char str[]="K&R,c89,c99,c11";
char str1[MAX] = "";
char str2[MAX] = "";
if (sscanf(str, "%[^,],%[^,]", str1, str2) == 2)
printf ("str1 : %s\nstr2 : %s\n", str1, str2);
return 0;
}
Example Use/Output
$ ./bin/sscanfcomma
str1 : K&R
str2 : c89
Also, consider protecting your arrays from overflow with, e.g.
if (sscanf(str, "%7[^,],%7[^,]", str1, str2) == 2)
Related
I am trying to read a file that contains lines in this format abc=1234. How can I make fscanf ignore the = and store str1="abc" and str2="1234"?
I tried this:
fscanf(fich1, "%[^=]=%[^=]" , palavra, num_char)
I'd recommend using fgets to read lines and then parse them with sscanf. But you can use the same principle for just fscanf if you want.
#include <stdio.h>
int main(void) {
char buf[100];
char str1[100];
char str2[100];
if(! fgets(buf, sizeof buf, stdin)) return 1;
if(sscanf(buf, "%[^=]=%s", str1, str2) != 2) return 1;
puts(str1);
puts(str2);
}
So what does %[^=]=%s do? First %[^=] reads everything until the first occurrence of = and stores it in str1. Then it reads a = and discards it. Then it reads a string to str2. And here you can see the problem with your format string. %[^=] expects the string to end with =, and you have another one at the end. So you would have a successful read of the string abc=1234=.
Note that %[^=] and %s treats white space a little differently. So if that's a concern, you need to account for that. For example with %[^=]=%[^\n].
And in order to avoid buffer overflow, you also might want to do %99[^=]=%99[^\n].
This post might be marked as a duplicate, but I did search online for this specific case and I couldn't find any examples similar to this. The following is a simplified version of my code.
I have the following lines of data stored with a text file named test.txt:
12345|This is a sentence|More words here
24792|This is another sentence|More words here again
The text in the test.txt file will always follow the format of <int>|<string>|<string>
I now want to store each of the sections separated by the delimiter | in a variable.
The following is my attempt:
uint32_t num;
char* str1, str2;
// the data variable is a char pointer to a single line retrieved from test.txt
sscanf(data, "%d|%s|%s", &num, str1, str2);
This code above would retrieve the correct value for num but would insert the first word from section two into str1, leaving the variable str2 as null. To my understanding, this was the case because the sscanf() function stops when it hits a space.
Is there an efficient way of storing each section into a variable?
As you noted, %s uses whitespace as the delimiter. To use | as the delimiter, use %[^|]. This matches any sequence of characters not including |.
And since num is unsigned, you should use %u, not %d.
sscanf(data, "%u|%[^|]|%[^|]", &num, str1, str2);
Don't forget to allocate memory for str1 and str2 to point to; scanf() won't do that automatically.
Your variable declarations are also wrong. It needs to be:
char *str1, *str2;
Your declaration is equivalent to:
char *str1;
char str2;
Say I have:
....
char aLine;
char inputLine[1000];
scanf("%c", &aLine);
....
Now, I want to convert aLine into an array of char so that I can count how many characters in aLine. How can i do this?
Statement scanf("%c",... reads in a single character, so there is actually no need to count it. If you want to "convert" a single character into a string (for which you could then apply, for example, strlen()), write the character at a particular position. Don't forget to terminate the string with \0 (or 0x0) such that string functions like printf("%s"... or strlen() work correctly:
char aLine;
char inputLine[1000];
scanf("%c", &aLine);
inputLine[0] = aLine;
inputLine[1] = '\0';
printf("inputLine: '%s' has length %d", inputLine, strlen(inputLine));
or simply read in a complete line at once:
char inputLine[1000];
if (fgets(inputLine,1000,stdin)) {
printf("inputLine: '%s' has length %d", inputLine, strlen(inputLine));
}
I have written this code but it's not working. It is showing some extra characters in the end. Here's the code:
// Program to concate/join two string
#include<stdio.h>
#include<string.h>
main()
{
int i,j,n=0;
char str[100],str2[100],str3[100];
printf("Enter string 1:\n");
gets(str);
printf("Enter string 2:\n");
gets(str2);
for(i=0;str[i]!='\0';i++)
{
str3[i]=str[i];
n=n+1;
}
for(i=0,j=n;str2[i]!='\0';i++,j++)
{
str3[j]=str2[i];
}
printf("The concanted sring is: \n");
puts(str3);
}
Terminate the str3 string with '\0' after you finish the copy loop:
for(i=0,j=n;str2[i]!='\0';i++,j++)
{
str3[j]=str2[i];
}
str3[j] = '\0'; // proper termination of the `str3`.
Otherwise the str3will continue till first random '\0' in the memory is encountered. That is why you get extra characters when you print str3.
Also read this: gets() function in C and
Why is the gets function so dangerous that it should not be used?
Avoid gets() in your programs!
In C language, a string is a null-terminated array of characters.
It is showing some extra characters in the end.
Reason for this is that you are not adding null character at the end of string str3 after concatenating str2 to it. Add a null-character at the end of the concatenated string, like this:
str3[j] = '\0';
Also, you should not use gets(). It has been obsoleted. Instead, use fgets().
Additional:
Follow the good programming practice, make a habit of specifying int as the return type of main function.
You can use one of best string manipulation function "strcat()" to concatenate to strings easily. try using below solution :
#include <stdio.h>
#include <string.h>
int main()
{
char str1[] = "Hello" , str2[] = "There";
//concatenates str1 and str2 and resultant string is stored in str1.
strcat(str1,str2);
puts(str1);
puts(str2);
return 0;
}
Output:
HelloThere
There
I`ve been trying to this for quite a while now and after some research I had no success, so my last resort was asking a question. My input looks like this:
1.0.0.0/255.0.0.0/127.0.0.1/1112
1.2.0.0/255.255.0.0/2.4.6.9/1112
1.2.3.0/255.255.255.0/1.2.3.1/111
I need to extract 4 strings from each line, so for exemple the first line would give me
s1 = 1.0.0.0
s2 = 255.0.0.0
s3 = 127.0.0.1
s4 = 1112
Here is what I have tried:
scanf("%s/%s/%s/%s", str1, str2, str3, str4); // This doesn't consume the "/"
scanf("%[^/]s%[^/]s%[^/]s%[^/]s", str1, str2, str3, str4); // This only gets the first string
scanf(""%[^\n]s%*c%s%*c%s%*c%s", str1, str2, str3, str4); // Hera %*c was supposed to consume the "/" and do not store it, it doen't happen tho
How can I get the 4 strings from each input line using a single scanf inside a while (!feof(fileIn)) ? Thank you.
There are a few issues with the posted code. The scanset directive is %[]; there is no s in this. The format strings using %[^/]s are attempting to match a literal s in the input. But this will always fail because %[^/] matches any character except for /. When a / is encountered, the match fails and the / character is left in the input stream. It is this character which must be consumed before continuing on to the next input field.
Also, note that while(!feof(file)){} is always wrong. Instead, try fetching input by lines using fgets(), and parsing with sscanf(). The fgets() function returns a null pointer when end-of-file is reached.
Further, you should always specify a maximum width when reading strings with scanf() family functions to avoid buffer overflow.
Here is an example program:
#include <stdio.h>
int main(void)
{
char input[4096];
char str1[100];
char str2[100];
char str3[100];
char str4[100];
while (fgets(input, sizeof input, stdin)) {
sscanf(input, " %99[^/]/ %99[^/]/ %99[^/]/ %99[^/]",
str1, str2, str3, str4);
puts(str1);
puts(str2);
puts(str3);
puts(str4);
}
return 0;
}
Sample interaction using sample input from the question:
λ> ./a.out < readstring_test.txt
1.0.0.0
255.0.0.0
127.0.0.1
1112
1.2.0.0
255.255.0.0
2.4.6.9
1112
1.2.3.0
255.255.255.0
1.2.3.1
111
You already got quite close: you missed to consume the delimiter in your second approach:
scanf("%[^/]/%[^/]/%[^/]/%[^/]", str1, str2, str3, str4);
should do the job.