So I've been working on some code that doesn't quite run as expected.
The code below should call a help function when only 'h' is typed in, and quit when 'q' is typed in. I can't really understand when is it when I press 'h' it gives an error:
printf("\n");
printf("Please input request (h-help, q-quit): ");
fgets(Input, 256, stdin);
char *array[256];
int count = 0;
char *token = strtok(Input, " ");
array[0] = token;
count++;
while(token != NULL)
{
int i = 1;
token = strtok(NULL, " ");
array[i] = token;
i++;
count++;
}
if(count == 1)
{
if(strlen(array[0]) == 2)
{
if(array[0] == 'h')
{
TRIGhelp();
return 0;
}
if(array[0] == 'q')
{
return 0;
}
}
else
{
printf("Error: Illegal input!");
}
}
I have used a count variable because larger strings can be input. For example the user can input three numbers, or a string and three numbers, etc.
I have tried using strlen(array[0]) == 1 as well, it still prints out the error message.
Thanks in advance!
Lots of problems here, but I'll concentrate on strtok as that is what you are asking about.
You're reading a line from the input with fgets but then tokenize only on space characters. Every line will end with a newline (\n) so what do you want to do with it? Users might also enter tabs and on some systems you might get \r characters at the end of the line. So you probably want
token = strtok(Input, " \t\r\n");
in order to tokenize on ALL whitespace, not just spaces.
Related
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;
}
char ad[8];
char ct[40];
printf("postal code: ");
scanf(" %[^\n]7s", ad);
printf("city: ");
scanf(" %[^\n]40s", ct);
printf("Address: |%s|%s\n", ad, ct);
sample input for ad: m2r 3r3 t4t .
output should be: m2r 3r3 .
but
output is: m2r 3r3 t4t
I've had a lot more luck with fgetc than with scanf although it needs some additional code to work smoothly, this just emphasizes what a hassle user entry can be:
char ad[8];
int maxlen = 7; //must be 1 less than array size for terminator
char a = '0';
int count = 0;
while (a != '\n' && count < maxlen) { //read until newline or size limit
a = fgetc(stdin);
ad[count] = a;
count++;
}
if (a == '\n') { //case: user entry < maxlen
buffer[count - 1] = '\0'; //get rid of newline char
}
else { //case: user entry >= maxlen
buffer[count] = '\0'; //terminate the string
do {
a = fgetc(stdin);
} while (a != '\n') //safely flush stdin so next entry works
}
Granted this looks like a ridiculous amount of code but you can stick it in a reusable ```getEntry`` function. Also, just avoid user entry if at all possible especially when building your code. The above so far seems fairly foolproof, at least. It's what I'm now using so any bug-spotting is more than welcome.
If your intention is to read 7 characters and discard the rest of the input you can do:
char ad[8];
char ct[40];
printf("postal code: ");
scanf("%7s%*[^\n]", ad);
printf("city: ");
scanf("%40s%*[^\n]", ct);
printf("Address: |%s|%s\n", ad, ct);
The %7s will read 7 characters. And the %*[^\n] will read until the end of the line and discard the result.
And just to emphasize, I'm not advocating to use scanf() but if you really want to the above code will do the trick.
A string S is passed as the input. The program must print the number of articles in S.
I have no idea about this problem. Help me to find a solution to this problem.
Input:
I went to a movie yesterday along with an old man.
Output:
2
There are two articles in the string.
I don't know exactly where your problem is, so I hope that this could help you
You can enter a text witch scanf. To split this string use strtok and for the comperison strcmp.
Also look:
https://devdocs.io/c/string/byte/strtok
https://devdocs.io/c/string/byte/strcmp
so here is how it can look like:
int main()
{
char arr[MAX];
printf("Input: ");
scanf("%[^\n]s",arr);
int count = 0;
char *token = strtok(arr, " ");
while(token)
{
if(strcmp(token, "an") == 0|| strcmp(token, "a") == 0 || strcmp(token, "the") == 0)
count++;
if(strcmp(token, "An") == 0|| strcmp(token, "A") == 0 || strcmp(token, "The") == 0)
count++;
token = strtok(NULL, " ");
}
printf("Output: %d", count);
return 0;
}
you could make an char array for the articles and than interate it. And don't foget to inlcude the librarys for this ;)
My assignment is to write a function that takes an input string from a user, tokenize it into several strings each containing an individual word from the input sentence, and then reverses the sentence. The result will be the sentence input but with the words in the reverse order.
For now, I just have the function taking in the input, tokenizing it into individual words, storing those words into an array, and printing out each individual word in order. I do not have the process for reversing the order of the words written yet.
Here is the code for the function i have handling this so far:
void reverse(void){
printf("\n\n%s\n", "Reverse words in String: ");
char input[200];
printf("\n%s", "Enter string\n> ");
scanf("%s", &input);
char reverseSentence[200];
char sentenceParts[20][200];
int wordCount = 0;
char *thisWord = strtok(input, " ");
strcpy(sentenceParts[wordCount], thisWord);
wordCount++;
while(thisWord != NULL){
thisWord = strtok(NULL, " ");
strcpy(sentenceParts[wordCount], thisWord);
wordCount++;
}
printf("\n\n");
for(int i = 0; i < wordCount + 1; ++i){
printf("%s%s", sentenceParts[i], " ");
}
}
The problem lies in the while statement:
while(thisWord != NULL){
thisWord = strtok(NULL, " ");
strcpy(sentenceParts[wordCount], thisWord);
wordCount++;
}
The program exits with a segmentation fault error at the strcpy statement. I cannot understand for the life of me why it is doing this. It seems like it worked just fine outside of the while loop.
Any thoughts? I've been stuck on this for quite a bit now and can't find too many other resources out there to help.
Updating thisWord with the next token should happen at the end of the loop body. As is, you'll eventually update thisWord with a NULL, and then call strcpy with a NULL. And that is your segfault.
So the loop should look like this:
char *thisWord = strtok(input, " ");
while(thisWord != NULL){
strcpy(sentenceParts[wordCount], thisWord);
wordCount++;
thisWord = strtok(NULL, " ");
}
The other problem (pointed out by #WhozCraig in the comments) is that you are inputting the line using scanf("%s", ...). That doesn't work because scanf will stop at the first whitespace character. Hence, you'll only get one word at a time from scanf. To get an entire line, use the fgets function.
I am in the process of writing a C program that parses a string and tokenizing it by breaking the string characters into words that are seperated by white space. My question is when i run my current program:
#include <stdio.h>
#include <stdlib.h>
int main()
{
char input[20];
printf("Please enter your word:\n");
scanf("%c", &input);
printf("%c", input[1]);
return 0;
}
If i was to enter the word "This", i would expect to get back "h" when i run the program but instead i get a downwards pointing arrow. However, when the input is set to print out input[0] i get back a "T".
Edit: I have modified my code so that it prints out the whole string now which i will show below
int main()
{
char input[20];
printf("Please enter your words:\n");
scanf("%s", input);
printf("%s", input);
return 0;
}
My goal is to be able to break that string into chars that i can search through to find whitespace and thus being able to isolate those words for example, if my input was "This is bad" i'd like the code to print out
This
is
bad
Edit:
I have modified my code to fit one of these answers but the problem i run into now is that it won't compile
int main()
{
char input[20];
printf("Please enter your words:\n");
size_t offset = 0;
do
{
scanf("%c", input + offset);
offset++;
}
while(offset < sizeof(input) && input[offset - 1] != '\n');
}
printf("%c", input[]);
return 0;
Problems:
1) scanf("%c", input); only set the first element of the array input.
2) printf("%c", input[1]); prints the second element of the array input, which has uninitialized data in it.
Solution:
Small state machine. No limit on string size like 20.
#include <ctype.h>
#include <stdio.h>
int main() {
int ch = fgetc(stdin);
while (ch != EOF) {
while (isspace(ch)) {
// If only 1 line of input allowed, then add
if (ch == '\n') return 0;;
ch = fgetc(stdin);
}
if (ch != EOF) {
do {
fputc(ch, stdout);
ch = fgetc(stdin);
} while (ch != EOF && !isspace(ch));
fputc('\n', stdout);
}
}
return 0;
}
scanf("%c", &input); does not do what you think it does.
First of all, %c scans only a single character: http://www.cplusplus.com/reference/cstdio/scanf/
Second, array's name is already a pointer to it's first element, so stating &input you make a pointer to a pointer, so instead of storing your character in array's first element you store it in pointer to the array which is a very bad thing.
If you really want to use scanf, I recommend a loop:
size_t offset = 0;
do
{
scanf("%c", input + offset);
offset++;
}
while(offset < sizeof(input) && input[offset - 1] != '\n');
Using scanf("%s", input") leaves you vulnerable to buffer overflow attacks if the word is longer than 20 characters http://en.wikipedia.org/wiki/Buffer_overflow
In my example I assumed, that you want to finish your word with a newline character.
EDIT: In scanf documentation is also a good example:
scanf("%19s", input);
It scans no more than 19 characters, which also prevent buffer overflow. But if you want to change input size, you have to change it two places.
You can use
char * strtok ( char * str, const char * delimiters );
to tokenize your string. If you have your input in input[] array and want to tokenize the string accoring to whitespace character, you can do the following :
char *ptr;
ptr = strtok(input, " ");
while(ptr != NULL) {
printf("%s\n", ptr);
ptr = strtok(NULL, " ");
}
Only the first call to strtok() requires the character array as input. Specifying NULL in the next calls means that it will operate on the same character array.
Your scanf only picks up the first character, input[1] contains random garbage. Use scanf("%19s", input) instead.