strtok() strcat() Unexpected output - c

#include "stdio.h"
#include "string.h"
int main(){
int counter;
char *token;
char s[]={"I am John"};
char con[256];
token = strtok(s," ");
while(token != NULL){
if (counter==0){
strcat(con,token);
token = strtok(NULL," ");
counter++;
}else{
strcat(con,token);
token = strtok(NULL," ");
strcat(con," ");
}
}
printf("%s\n",con);
return 0;
}`
printf()'s output is "I am John"
I would like the output to be "am John"

strcat expects the first argument to be null-terminated, which isn't guaranteed by declaring con, since its uninitialized. so the invocation of strcat is undefined behavior. Therefore your program is undefined behavior. Do
con[0] = '\0';
to resolve this issue.
counter is uninitialized. Using it in an expression is undefined behavior too.

counter and array con is uninitialized . So it will lead to erroneous results.

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;
}

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;
}

Take user input and then do execvp

So I have the following C code which asks the user to give a command (valid in unix), and then I have to take the string and split it in an array in order to execute the command that the user gave with execvp(). It compiles but the execvp doesn't seem to work. Is something wrong in the way I split the user's input in an array? PS: Some of the includes aren't neccessary but it's not the final program.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <signal.h>
main() {
char str[64];
int i =0;
char *p = strtok(str," ");
printf("Please give me a Unix command! :\n");
gets(str);
char *array[sizeof(str)];
while (p!=NULL) {
array[i++] = p;
p = strtok (NULL, " ");
}
execvp(str ,array);
perror("execvp");
}
The output I get when I run this is:
Please give me a Unix command! :
ls -l
execvp: No such file or directory
You're calling strtok(str, " ") before str has any information.
Simply call it after you get input:
main() {
char str[64];
char *array[sizeof(str)];
char *p = NULL;
int i = 0;
printf("Please give me a Unix command! :\n");
fgets(str, sizeof(str), stdin); // Use fgets instead of gets.
p = strtok(str," ");
while (p != NULL) {
array[i++] = p;
p = strtok(NULL, " ");
}
execvp(str, array);
}
The first problem as I see here is with
char *p = strtok(str," ");
as you're trying to read indeterminate values. str is not initialized, there's no guarantee that there is a null-terminator present there which makes this a string. So, you're essentially invoking undefined behavior.
That said,
gets(), it is dangerous as it lead to buffer overflow. use fgets() instead.
for an array variable, sizeof(str) does not give you the size of the content, it returns you the size of the whole array. You might want to use strlen() to get the length of the string, but remember, strlen() does not count the null-terminator.

Storing Pieces of a String using Strtok

#include <stdio.h>
#include <math.h>
#include <string.h>
int main(void)
{
int menuswitch=1;
int amountofstudents;
int fname[50];
int lname[50];
int grade[50];
int i;
char studentinfo[100];
printf("Enter Amount of Students: ");
scanf("%d", &amountofstudents);
for (i=0;i<amountofstudents;i++)
{
gets(studentinfo);
strcpy(fname[i], strtok(studentinfo, " "));
strcpy(lname[i], strtok(NULL, " "));
strcpy(grade[i], strtok(NULL, " "));
}
Alright need a little using strtok. I am trying to store pieces of an input string to sort later. I was thinking of using strtok to break the string then placing each piece in the corresponding array. Yet, every time I try I get an error in Visual Studios saying Access Violation. Thanks for the help ahead of time
The error is
First-chance exception at 0x5120F7B3 (msvcr110d.dll) in Lab 2.exe: 0xC0000005: Access violation reading location 0x00000000.
Unhandled exception at 0x5120F7B3 (msvcr110d.dll) in Lab 2.exe: 0xC0000005: Access violation reading location 0x00000000.
The input would be
FirstName Lastname 80(Grade)
One major problem is that you try to copy into integer values and not strings. Change the
integer arrays to arrays of strings:
...
char fname[50][100];
char lname[50][100];
char grade[50][100];
...
You also have a problem with the gets function (besides it being obseleted and should not be used), namely that the previous scanf doesn't remove the newline from the input buffer so the first gets call will see this empty newline and give you an empty line (which you do not check for).
This is simply solved by telling scanf to discard trailing whitespace by adding a space in the format string after the "%d":
scanf("%d ", &amountofstudents);
/* ^ */
/* | */
/* Note space */
Instead of gets, you should be using fgets:
fgets(studentinfo, sizeof(studentinfo), stdin);
And finally, always check for errors!
a potential issue is the scanf/gets combo. use instead fgets() and convert when appropriate to integer using atoi() it is also good to do a sanity check on what is returned from strtok (it is never good to assume anything about input)
char* token = strtok(studentinfo, " ");
if ( strlen(token) < sizeof(fname[i]) )
{
strcpy(fname[i], token);
...
you have also declared your strings as integer arrays, they should be char
e.g. char fname[50];
The problem you have is that you have declared three variables (fname, lname, and grade) as char[] (arrays) (well, that is the type you meant to use), but you want to prompt for and keep around a bunch of students information. And you later try to copy from strtok() into what you want to be a char[], but since you dereferenced fname[i] (lname[i], grade[i]), they are of type char, rather than char[].
You will need stdlib.h for exit,
#include <stdio.h>
#include <stdlib.h> //for exit
#include <string.h>
//#include <math.h> //you don't need this, yet
#define STUDLIMIT (100)
You can either create an array of fname[], lname[], grade[], (see here: http://www.cs.swarthmore.edu/~newhall/unixhelp/C_arrays.html),
int main(void)
{
//int menuswitch=1; //you aren't using this
int amountofstudents;
char studentinfo[100];
char fname[STUDLIMIT][50];
char lname[STUDLIMIT][50];
char grade[STUDLIMIT][50];
int ndx;
printf("Enter Amount of Students: ");
if( (fscanf(stdin,"%d ", &amountofstudents)<=0)
|| (amountofstudents<1) || (amountofstudents>STUDLIMIT) )
{
printf("need %d to %d studends\n",1,STUDLIMIT); exit(0);
}
for (ndx=0;ndx<amountofstudents;ndx++)
{
printf("Student: "); fflush(stdout);
fgets(studentinfo,sizeof(studentinfo),stdin);
strcpy(fname[ndx], strtok(studentinfo, " "));
strcpy(lname[ndx], strtok(NULL, " "));
strcpy(grade[ndx], strtok(NULL, " "));
}
}
Or you can create a struct(ure) to hold the entered student information, and instantiate an array of these student records, one for each student you enter and store,
typedef struct student
{
char fname[50];
char lname[50];
char grade[50];
} StudentObj;
int StudentCopy(StudentObj*sp,char*fname,char*lname,char*grade)
{
if(!sp || !fname || !lname || !grade ) return -1;
strcpy(sp->fname, fname);
strcpy(sp->fname, lname);
strcpy(sp->fname, grade);
}
StudentObj students[STUDLIMIT];
int main(void)
{
//int menuswitch=1; //you aren't using this
int amountofstudents;
char studentinfo[100];
char fname[50];
char lname[50];
char grade[50];
int ndx;
printf("Enter Amount of Students: ");
if( (fscanf(stdin,"%d ",&amountofstudents)<=0)
|| (amountofstudents<1) || (amountofstudents>STUDLIMIT) )
{
printf("need %d to %d studends\n",1,STUDLIMIT); exit(0);
}
for (ndx=0;ndx<amountofstudents;ndx++)
{
printf("Student: "); fflush(stdout);
fgets(studentinfo,sizeof(studentinfo),stdin);
strcpy(fname, strtok(studentinfo, " "));
strcpy(lname, strtok(NULL, " "));
strcpy(grade, strtok(NULL, " \n\r"));
StudentCopy(&(students[ndx]),fname,lname,grade);
}
}

Segmentation fault (core dumped) issue

I am trying to read in input from a user, and then tokenize each word and put each word into an array of strings. At the end, the contents of the array are printed out for debugging. My code is below.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
int MAX_INPUT_SIZE = 200;
volatile int running = 1;
while(running) {
char input[MAX_INPUT_SIZE];
char tokens[100];
printf("shell> ");
fgets(input, MAX_INPUT_SIZE, stdin);
//tokenize input string, put each token into an array
char *space;
space = strtok(input, " ");
tokens[0] = space;
int i = 1;
while (space != NULL) {
space = strtok(NULL, " ");
tokens[i] = space;
++i;
}
for(i = 0; tokens[i] != NULL; i++) {
printf(tokens[i]);
printf("\n");
}
printf("\n"); //clear any extra spaces
//return (EXIT_SUCCESS);
}
}
After I type in my input at the "shell> " prompt, gcc gives me the following error:
Segmentation fault (core dumped)
Any idea as to why this error is happening? Thanks in advance for your help!
char tokens[100];
This declaration should be array of array of characters(two dimensional character array) to hold Multiple strings
char tokens[100][30];
//in your case this wont work because you require pointers
//while dealing with `strtok()`
USE
Array of character pointers
char *tokens[100];
This is also wrong
printf(tokens[i]);
You should use printf with format specifier %s while printing string.
change like this
printf("%s", tokens[i]);

Resources