sscanf get string until second symbol (include one) - c

How to get string until second symbol through sscanf?
for example:
char *str = "struct1.struct2.struct3.int";
char buf[256] = {0};
sscanf(str, "", buf); //have any format string could get string until second dot?

sscanf get string until second symbol (include one)
How to get string until second symbol through sscanf?
Not generally possible with a single use of sscanf().
Certainly, without a lot of work, a more involved use of sscanf() will work for many input strings, yet fail for select ones1. sscanf() is not the best fit here for this task.
strchr(), strcspn() better suited.
#include <string.h>
#include<stdlib.h>
// Return offset to 2nd needle occurrence
// or end of string, if not found.
size_t foo(const char *haystack, const char *needle) {
size_t offset = strcspn(haystack, needle);
if (haystack[offset]) {
offset++;
offset += strcspn(haystack + offset, needle);
}
return offset;
}
#include <stdio.h>
int main() {
const char *haystack = "struct1.struct2.struct3.int";
printf("<%.*s>\n", (int) foo(haystack, "."), haystack);
}
Output
<struct1.struct2>
1 Consider: "struct1.struct2", "struct1..", "..struct2", ".struct2.", "..", ".", "".

You can use a * to tell scanf to ignore an element:
const char *str = "struct1.struct2.struct3.int";
int main() {
char buf[256];
int i = sscanf(str, "%*[^.].%[^.]", buf);
printf("%d >%s<\n", i, buf);
return 0;
}
This outputs as expected:
1 >struct2<
because exactly 1 element was assigned even if another one was parsed.

Related

How do I the rest of the string after a particular character in C

I want to get the rest of the string after the first "/" symbol.
The expectation I wanna get is:
index/homepage/component.html/sdfsdf
int main(int argc, char *argv[]){
char link[] = "www.google.com/index/homepage/component.html/sdfsdf";
char *token;
char *temp[1000];
int i=0;
token = strtok(link, "/");
while(token != NULL){
temp[i] = token;
token = strtok(NULL, "/");
++i;
}
printf("the parse string: %s\n",*temp);
return 0;
}
the parse string: www.google.com
The other answers have covered a more prefered method, that is strchr(), but for compleatness this is how it can be done using regular expressions and sscanf.
this works by grabing everything befor the '/' and ignoring it by using %*[^/] (the * means it will not put it into a variable), then on the other side of '/' just getting everything till the end of line char is hit by %[^\n]
#include <stdio.h>
char link[] = "www.google.com/index/homepage/component.html/sdfsdf";
int main(int argc, char **argv){
char buff[128];
// Seporate string after first "/"
// %*[^/] goes untill it finds '/' and stops, but wont put it in a var
// "/" will eat the '/' charater
// %[^\n] goes untill it finds the '\n' char and puts it into buff
sscanf(link, "%*[^/]/%[^\n]", buff);
printf("%s\n", buff);
}
edit: added clarification of the '*'
Since you have one target character you are after in a longer string, to find the first occurrence, you can simply use strchr to return a pointer to the desired character within the larger string. In this case the first '/'. To use strchr to locate the pointer associated with the first '/' your call would simply be:
char *p = strchr (link, '/');
If p is not NULL then it has been found within the string. Recall, the character found was a separator character that was not wanted, so you advance the pointer by 1 so that it is pointing to the first character after the '/'.
A simple call to strlen() at that point will tell you how many characters you must copy from link to your string where you are saving the results. Then using the length, you can simply call memcpy to copy from link beginning at the pointer location to the end of the string (including the nul-terminating character) to obtain the wanted characters. A short example would be:
#include <stdio.h>
#include <string.h>
#define MAXTOK 2048
int main (void) {
char link[] = "www.google.com/index/homepage/component.html/sdfsdf",
*p = link,
token[MAXTOK]; /* declare array to hold results */
if ((p = strchr (link, '/'))) { /* check whether '/' found in line */
size_t len = strlen (++p); /* advance pointer by 1, get length */
if (len > MAXTOK - 1) { /* check if length exceeds available */
fputs ("error: string exceeds allowable length.\n", stderr);
return 1;
}
memcpy (token, p, len + 1); /* copy remaining part of string */
printf ("%s\n", token); /* output it */
}
}
EXample Use/Output
$ ./bin/charstr_rest
index/homepage/component.html/sdfsdf
Providing the desired result string. Look things over and let me know if you have questions.
Hope this Helps..First find out the Position of '/' Character in the String then build your Substring,have mentioned on each block of code Whats it does...
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[])
{
char link[] = "www.google.com/index/homepage/component.html/sdfsdf";
char linktemp[50];
int i=0,c=0;
////Finding the Position of First '/'
for(i=0;i<strlen(link);i++)
{
if(link[i]=='/')
{
break;
}
}
//If no '/' Character found
if(i==strlen(link))
{
printf("No '/' Character found in the String");
return 0;
}
////Creating the Substring
while(c<strlen(link)-i)
{
linktemp[c]=link[i+c+1];
c++;
}
linktemp[c] ='\0';
printf("the parse string: %s\n",linktemp);
return 0;
}

Strtok outputting just a part of the string

#include <stdio.h>
#include <string.h>
int main(){
char name[] = "eseumdesconhecidolheoferecerflores.issoeimpulse.cities";
char *str;
printf("%s\n", name)
str = strtok(name, ".cities");
printf("%s\n", str);
return 0;
}
This is the output:
eseumdesconhecidolheoferecerflores.issoeimpulse.cities
umd
I have no idea what is happening at all. What I want is for the output of strtok to be a pointer to "eseumdesconhecidolheoferecerflores.issoeimpulse"
The delimiter argument to strtok is a string containing individual characters used to separate the string.
You specified delimiters ., c, i, t, e, and s.
So it's no surprise the output is umd for the first token, since it is surrounded by characters in your delimiter string.
If you want to find a whole string, you should use strstr instead.
For example:
char name[] = "eseumdesconhecidolheoferecerflores.issoeimpulse.cities";
char *pos;
pos = strstr(name, ".cities");
if (pos)
{
*pos = '\0';
printf("%s\n", name);
}

C - Is this the right way to use strtok in the following situation

If i have a string that contains 10X15. And i want to separate the 10 and 15. Would the following code be correct. I am concerned about the second part of the code, is putting "NULL" there the right thing to do.
char * stringSixrows = strtok(stringSix[0], "X");
char * stringSixcollumns = strtok(NULL, "NULL");
//I put the second null there cause its the end of string, im not sure if its right though.
I'd say the "canonical" way to obtain the "pointer to the remaining string" is:
strtok(NULL, "")
strtok searches for any of the delimiters in the provided string, so if you don't provide any delimiters, it cannot find anything and thus only stops at the end of the input string.
example
#include <stdio.h>
#include <string.h>
int main(void){
char stringSix[] = "10X15";
char *stringSixrows = strtok(stringSix, "X");
char *stringSixcolumns = strtok(NULL, "X");
printf("%s, %s\n", stringSixrows, stringSixcolumns);
return 0;
}
another way
char stringSix[] = "10X15";
char stringSixrows[3];
char stringSixcolumns[3];
char *p;
if(NULL!=(p = strchr(stringSix, 'X')))
*p = '\0';
else {
printf("invalid format\n");
return -1;
}
strcpy(stringSixrows, stringSix);
strcpy(stringSixcolumns, p+1);
printf("%s, %s\n", stringSixrows, stringSixcolumns);
const char *stringSix = "10X15";
int stringSixrows;
int stringSixcolumns;
if(2==sscanf(stringSix, "%dX%d", &stringSixrows, &stringSixcolumns))
printf("%d, %d\n", stringSixrows, stringSixcolumns);
You can use strtol to convert the string to numbers as well as seek to the next string. Below code safely does the intended operation:
char stringSix[] = "10X15";
char * pEnd;
long firstNumber = strtol (stringSix,&pEnd, 10);
pEnd = strtok(pEnd, "");
long secondNumber = strtol (pEnd,&pEnd, 10);

read the characters between special characters in C

I'm new to C language and I need a help on String functions.
I have a string variable called mcname upon which I would like to compare the characters between special characters.
For example:
*mcname="G2-99-77"
I expect the output to be 99 as this is between the - characters.
How can I do this in C please?
Travel the string (walking pointer) till u hit a special character.
Then start copying the characters into seperate array untill u hit the next special character (Place a null character when u encounter the special character second time)
You can do this by using strtok or sscanf
using sscanf:
#include <stdio.h>
int main()
{
char str[64];
int out;
char mcname[] = "G2-99-77";
sscanf(mcname, "%[^-]-%d", str, &out);
printf("%d\n", out);
return 0;
}
Using strtok:
#include <stdio.h>
#include <string.h>
int main()
{
char *str;
int out;
char mcname[] = "G2-99-77";
str = strtok(mcname, "-");
str = strtok (NULL, "-");
out = atoi(str);
printf("%d\n", out);
return 0;
}
sscanf() has great flexibility. Used correctly, code may readily parse a string.
Be sure to test the sscanf() return value.
%2[A-Z0-9] means to scan up to 2 characters from the set 'A' to 'Z' and '0' to '9'.
Use %2[^-] if code goal is any 2 char other than '-'.
char *mcname = "G2-99-77";
char prefix[3];
char middle[3];
char suffix[3];
int cnt = sscanf(mcname, "%2[A-Z0-9]-%2[A-Z0-9]-%2[A-Z0-9]", prefix, middle,
suffix);
if (cnt != 3) {
puts("Parse Error\n");
}
else {
printf("Prefix:<%s> Middle:<%s> Suffix:<%s>\n", prefix, middle, suffix);
}

Using Pointers and strtok()

I'm building a linked list and need your assistance please as I'm new to C.
I need to input a string that looks like this: (word)_#_(year)_#_(DEFINITION(UPPER CASE))
Ex: Enter a string
Input: invest_#_1945_#_TRADE
Basically I'm looking to build a function that scans the DEFINITION and give's me back the word it relates to.
Enter a word to search in the dictionary
Input: TRADE
Output: Found "TREADE" in the word "invest"
So far I managed to come up using the strtok() function but right now I'm not sure what to do about printing the first word then.
Here's what I could come up with:
char split(char words[99],char *p)
{
p=strtok(words, "_#_");
while (p!=NULL)
{
printf("%s\n",p);
p = strtok(NULL, "_#_");
}
return 0;
}
int main()
{
char hello[99];
char *s = NULL;
printf("Enter a string you want to split\n");
scanf("%s", hello);
split(hello,s);
return 0;
}
Any ideas on what should I do?
I reckon that your problem is how to extract the three bits of information from your formatted string.
The function strtok does not work as you think it does: The second argument is not a literal delimiting string, but a string that serves as a set of characters that are delimiters.
In your case, sscanf seems to be the better choice:
#include <stdlib.h>
#include <stdio.h>
int main()
{
const char *line = "invest_#_1945 _#_TRADE ";
char word[40];
int year;
char def[40];
int n;
n = sscanf(line, "%40[^_]_#_%d_#_%40s", word, &year, def);
if (n == 3) {
printf("word: %s\n", word);
printf("year: %d\n", year);
printf("def'n: %s\n", def);
} else {
printf("Unrecognized line.\n");
}
return 0;
}
The function sscanf examines a given string according to a given pattern. Roughly, that pattern consists of format specifiers that begin with a percent sign, of spaces which denote any amount of white-space characters (including none) and of other characters that have to be matched varbatim. The format specifiers yield a result, which has to be stored. Therefore, for each specifier, a result variable must be given after the format string.
In this case, there are several chunks:
%40[^_] reads up to 40 characters that are not the underscore into a char array. This is a special case of reading a string. Strings in sscanf are really words and may not contain white space. The underscore, however, would be part of a string, so in order not to eat up the underscore of the first delimiter, you have to use the notation [^(chars)], which means: Any sequence of chars that do not contain the given chars. (The caret does the negation here, [(chars)] would mean any sequence of the given chars.)
_#_ matches the first delimiter literally, i.e. only if the next chars are underscore hash mark, underscore.
%d reads a decimal number into an integer. Note that the adress of the integer has to be given here with &.
_#_ matches the second delimiter.
%40s reads a string of up to 40 non-whitespace characters into a char array.
The function returns the number of matched results, which should be three if the line is valid. The function sscanf can be cumbersome, but is probably your best bet here for quick and dirty input.
#include <stdio.h>
#include <string.h>
char *strtokByWord_r(char *str, const char *word, char **store){
char *p, *ret;
if(str != NULL){
*store = str;
}
if(*store == NULL) return NULL;
p = strstr(ret=*store, word);
if(p){
*p='\0';
*store = p + strlen(word);
} else {
*store = NULL;
}
return ret;
}
char *strtokByWord(char *str, const char *word){
static char *store = NULL;
return strtokByWord_r(str, word, &store);
}
int main(){
char input[]="invest_#_1945_#_TRADE";
char *array[3];
char *p;
int i, size = sizeof(array)/sizeof(char*);
for(i=0, p=input;i<size;++i){
if(NULL!=(p=strtokByWord(p, "_#_"))){
array[i]=p;//strdup(p);
p=NULL;
} else {
array[i]=NULL;
break;
}
}
for(i = 0;i<size;++i)
printf("array[%d]=\"%s\"\n", i, array[i]);
/* result
array[0]="invest"
array[1]="1945"
array[2]="TRADE"
*/
return 0;
}

Resources