Taking a string, and parsing/tokenizing into smaller strings using hyphen delimiter - c

I am tasked with writing a C program that will take a string with hyphens in it, and check to see that the first group of the string (before the hyphen) is alphabet/letter only, the next group is numeric only, and the last group is alphabet/letter only. It is similar to this project: http://wps.aw.com/wps/media/objects/7257/7431666/Case_Studies/GaddisJavaCSO_CS6.pdf
So far I am stuck on splitting the string into 3 variables. I have read about strtok and manipulating the scanf function, but I haven't been successful:
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main ()
{
char serial [50];
char * part1 = NULL, part2 = NULL, part3 = NULL;
printf("Enter Serial Number:\n");
scanf("%s", serial);
part1 = strtok (serial, "-");
part2 = strtok(NULL, "-");
part3 = strtok(NULL, "-");
printf("You entered %s\n", part1);
printf("You entered %s\n", part2);
printf("You entered %s\n", part3);
return 0;
}

you are using strtok wrong, pass parameters to it and it should work fine.
char * pch = strtok (serial, "-" );
while (pch != NULL)
{
printf ("%s\n",pch);
pch = strtok (NULL, "-");
}
or in your example you need to define each as a char* :
char * part1= strtok (serial, "-");
char * part2 = strtok(NULL, "-");
char* part3 = strtok(NULL, "-")
StrTok + example

strcpy(part1, strtok(serial, "-"));//premise: string has hyphen
strcpy(part2, strtok(NULL, "-"));
strcpy(part3, strtok(NULL, "-"));

You could utilize scanf's formatting rules to read your strings directly from the input line.
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main ()
{
char part1[40], part2[40], part3[40];
int count, n;
do{
n = 0;
flushall();
printf("Enter Serial Number:\n");
count = scanf(" %39[A-Za-z]-%39[0-9]-%39[A-Za-z]%n", part1, part2, part3, &n);
if( count != 3 || n == 0 ){
printf("Recognize %i parts, %s\n", count, n == 0 ? "did not parse to the end" : "parsed to the end");
}
}while(count != 3 || n == 0);
printf("You entered %s\n", part1);
printf("You entered %s\n", part2);
printf("You entered %s\n", part3);
return 0;
}
This is quite a strict form of parsing the input and requires the user to keep the outer form. You can easily filter allowed strings by not using %s but rather something like %[0-9]. The best way for me to filter serialnumber inputs was always Regex if available... but i dont think this is part of your homework yet :)

Related

Taking multiple strings and integers in a single line

I want to take multiple integer and strings in a single line such as "45 A4 Paper 217" but I want to store string A4 Paper in a single char array. I tried using scanf but it scans until space for string.
int int1;
int int2;
char str1[81];
scanf("%d %s %d",&int1,&str1,&int2);
I want str1 to be A4 Paper in str1 array
The scanf family functions are known as a poor man's parser. They can easily parse blank separated tokens, but anything more complex is at best tricky, or even impossible - more exactly other tools should be used.
Your requirement is to accept in a single string any token until an integer token is found (token here being a blank delimited string). This is just not possible in single scanf.
If the type and number of blank characters does not matter, you could use a scanf loop first trying to find an integer, next getting tokens as string:
i = scanf("%d", &int1); // get first integer
if (i != 1) {
// error condition
}
char *cur = str1;
for(;;) {
if (1 == scanf("%d", &int2)) break; // ok we have found the second integer
i = scanf("%s", cur);
if (i != 1) {
// error condition
}
cur += strlen(cur); // move cur to end of string
*cur++ = ' '; // and add a space
}
if (cur != str1) {
cur[-1] = '\0'; // erase last space
}
This should detect read errors, but does not even try to control overflow of str1. It should be added for production grade code.
This is my solution
#include <stdio.h>
#include <string.h>
int main() {
int int1,int2;
char str[100],str1[81];
char *p;
scanf("%[^\n]s",str);
p = strtok (str," ");
sscanf(p, "%d", &int1);
p = strtok (NULL, " ");
strcpy(str1,p);
strcat(str1," ");
p = strtok (NULL, " ");
strcat(str1,p);
p = strtok (NULL, " ");
sscanf(p, "%d", &int2);
printf("%d %s %d",int1,str1,int2);
return 0;
}

How can i print the whole sentence without punctuations? [duplicate]

This question already has answers here:
Using strtok in c
(7 answers)
Closed 3 years ago.
I couldn't print the whole output in a string.
All I know is that %s should work like a loop
for example
printf("%s", str);
works the same as puts(str);
#include <stdio.h>
#include <string.h>
int main (){
char str[]="Hello:, student; how are you? This task is easy!";
char *token;
char del[] = ", ; : ? !", cp[80];
int count;
strcpy(cp, str);
token = strtok(str, del);
count = 0;
while( token != NULL )
{
printf("%s\n", token);
token = strtok(NULL, del);
count++;
}
strtok(str, del);
printf("Your sentence has %d words\n", count);
puts("The sentence without punctuation charachters is: \n ");
puts(str); // This should where it show me the output
return 0 ;
}
// I tried to follow the instruction I had to write this code in this form.
// This is the output that I suppose to get
Hello
student
how
are
you
This
task
is
easy
Your sentence has 11 words
The sentence without punctuation characters is:
Hello student how are you This task is easy
// all I got is ( ignore the extra line between each word)
Hello
student
how
are
you
This
task
is
easy
Your sentence has 11 words
The sentence without punctuation characters is:
Hello
strtok(str, del); modifies its first parameter adding null characters inside, this is why when you print str after the calls of strtok you got only the first token
you save the string doing strcpy(cp, str); but you do not use it, and you also hope 80 is enough ...
A proposal placing the words in cp then printing it :
#include <stdio.h>
#include <string.h>
int main (){
char str[]="Hello:, student; how are you? This task is easy!";
char *token;
char del[] = ", ; : ? !", cp[sizeof(str) + 1];
int count;
size_t pos = 0;
token = strtok(str, del);
count = 0;
while( token != NULL )
{
printf("%s\n", token);
strcpy(cp + pos, token);
pos += strlen(token);
cp[pos++] = ' ';
token = strtok(NULL, del);
count++;
}
cp[(pos == 0) ? 0 : (pos - 1)] = 0;
printf("Your sentence has %d words\n", count);
puts("The sentence without punctuation characters is:");
puts(cp); // This should where it show me the output
return 0 ;
}
Compilation and execution :
pi#raspberrypi:/tmp $ gcc -pedantic -Wall -Wextra c.c
pi#raspberrypi:/tmp $ ./a.out
Hello
student
how
are
you
This
task
is
easy
Your sentence has 9 words
The sentence without punctuation characters is:
Hello student how are you This task is easy
pi#raspberrypi:/tmp $

strtok is causing a Segmentation Fault

I have to get the third word in a string and wanted to use strtok. Now, the first printf works but after that I get a Seg Fault. So tokenizedString = strtok(NULL, " "); must be causing the issue, right?
Just for context: I'm looking for the third word in a string and there can be as many spaces as possible between the words.
#include <string.h>
#include <stdio.h>
char *tokenizeString(char *userCommand)
{
char *tokenizedString;
int counterForToken;
tokenizedString = strtok(userCommand, " ");
for(counterForToken = 0; counterForToken != 3; counterForToken++)
{
printf("%s\n", tokenizedString);
tokenizedString = strtok(NULL, " ");
if(tokenizedString == NULL)
{
break;
}
}
printf("%s\n", tokenizedString);
return tokenizedString;
}
int main(void)
{
char userCommand[255] = {0};
fgets(userCommand, sizeof(userCommand), stdin);
tokenizeString(userCommand);
}
Now, the first printf works but after that I get a Seg Fault. So tokenizedString = strtok(NULL, " "); must be causing the issue, right?
No, that is very poor correlation. The issue is in fact in the second call to printf. You can pass it tokenizedString when tokenizedString == NULL. The format specified %s is specified to expect a valid pointer to the first character of a zero terminated array of characters. Passing it NULL is illegal and leads to undefined behavior (causing a crash for instance). The fix is simple: check for a null pointer value. And the same applies to the first iteration of the loop, of course
char *tokenizeString(char *userCommand)
{
char *tokenizedString;
int counterForToken;
tokenizedString = strtok(userCommand, " ");
for(counterForToken = 0; counterForToken != 3 && tokenizedString != NULL; counterForToken++)
{
printf("%s\n", tokenizedString);
tokenizedString = strtok(NULL, " ");
}
if(tokenizedString != NULL)
printf("%s\n", tokenizedString);
return tokenizedString;
}

strcasecmp is not returning zero

I want to know why strcasecmp() is returning 0 the first time I use it but not the second.
In this example i'm specifically entering "hello world" into standard input.
Instead of printing 0 0 it's printing 0 10. I have the following code.
#include "stdio.h"
#include "string.h"
int main(void) {
char input[1000];
char *a;
fgets(input, 1000, stdin);
a = strtok(input, " ");
printf("%d\n",strcasecmp(a,"hello")); //returns 0
a = strtok(NULL, " ");
printf("%d\n",strcasecmp(a,"world")); //returns 10
return 0;
}
What am I doing wrong?
The newline, you have entered after hello world is part of the world token because you use space as token separator.
If you use strtok(input, " \n"); instead of strtok(input, " "); the program will behave correctly. In fact, you probably want to use tabulator as token separator as well.
The whole program will be:
#include "stdio.h"
#include "string.h"
int main(void) {
char input[1000];
char *a;
fgets(input, 1000, stdin);
a = strtok(input, " \n\t");
if (a == NULL) return(-1);
printf("%d\n",strcasecmp(a,"hello"));
a = strtok(NULL, " \n\t");
if (a == NULL) return(-1);
printf("%d\n",strcasecmp(a,"world"));
return 0;
}

strtok return string?

just having a little issue with strtok and strcmp.
I'm trying to compare the input of a user via fgets to some predetermined string:
char *token[100];
fgets(s, sizeof(s), stdin)
token[0] = strtok(s, " "); // Get first word
printf("tok: %s", token[0]);
printf("cmp: %d\n", strcmp(token[0], "/bin/echo");
Obviously it's not all the code but this shows my problem - if I enter "/bin/echo ..." (or anything for that matter), it will be put into token[0], and get printed. It prints correctly but when it prints the cmp value it's never 0. For /bin/echo, the cmp value is 1 for some reason.
Thanks.
EDIT to clear up confusion about s and token:
char s[1024];
char *token[100];
EDIT 2 - Added some other test cases:
I entered "/bin/echo hello world" to stdin
token[0] = strtok(s, " \n\0"); // Get first word
printf("token[0] is: %s", token[0]);
printf("cmp: %d\n", strcmp(token[0], "/bin/echo"));
Output:
token[0] is: /bin/echo
cmp: 1
And then I tried hardcoding the tokened string:
char str[] = "/bin/echo hello world";
token[0] = strtok(str, " ");
printf("token[0] is: %s", token[0]);
printf("cmp: %d\n", strcmp(token[0], "/bin/echo"));
Output:
token[0] is: /bin/echo
cmp: 0
here i have made small program
#include<string.h>
#include<stdio.h>
int main()
{
char str[] ="/bin/echo this is something";
char * token[100];
token[0] = strtok (str," ");
token[0] = strtok(str, " "); // Get first word
printf("cmp: %d\n", strcmp(token[0], "/bin/echo"));
return 0;
}
Here i have statically stored input string instead of fgets()
That works fine.
see http://codepad.org/IrGAXT8f
Use
char token[1000];
strcpy(token,strtok(s," "));
string's can't be assigned directly like this in c :)
also, include string.h
One needs to allocate memory dynamically for copying strings. Read about dynamic memory management first (malloc, calloc, etc...)
EDIT:
http://ideone.com/0UxEwO - works for me
#include <stdio.h>
#include <string.h>
int main()
{
char s[1024];
char *token[100];
fgets(s, sizeof(s), stdin);
token[0] = strtok(s, " \n\0");
printf("token[0] is: %s", token[0]);
printf("cmp: %d\n", strcmp(token[0], "/bin/echo"));
}

Resources