I am trying to make a program that prints out a sentence word by word using a pointer. I am having hard time finding the problem.
char str[100];
char *p;
printf("\nSentence: ");
scanf("%s", str);
p=str;
while(*p!='\0'){
if(*p == ' '){
printf("\n");
}else{
printf("%c", *p);
}
p++;
}
Using of the function scanf with the format "%s" skips leading white spaces and reads characters until a white space is encountered.
So you can not enter a sentence using this format,
Instead use the standard function fgets.
Moreover take into account that the user can separate words with several spaces or tabs. In this case your output will be invalid because there will be many empty lines.
It is more efficient to use the standard C functions strspn and strcspn.
Here is a demonstrative program.
#include <stdio.h>
#include <string.h>
int main(void)
{
enum { N = 100 };
char str[N] = "";
printf( "Enter a Sentence: " );
fgets( str, N, stdin );
str[ strcspn( str, "\n" ) ] = '\0';
const char *p = str;
const char *delim = " \t";
while ( *p )
{
p += strspn( p, delim );
const char *q = p;
p += strcspn( p, delim );
if ( p != q )
{
printf( "%*.*s\n", ( int )( p - q ), ( int )( p - q ), q );
}
}
return 0;
}
If for example to enter the following statement
Have a nice day Luka Milicevic
then the program output will be
Enter a Sentence: Have a nice day Luka Milicevic
Have
a
nice
day
Luka
Milicevic
You can use gets_s instead of scanf("%s"):
gets_s(str, sizeof(str));
Then you code will work fine.
scanf("%s") will get only one word from standard input.
On the other hand, gets_s will get a whole line.
But gets_s() can work only on Visual Studio, in order to make it portable, it's better to use fgets().
scanf reads the string until the first whitespace. If you input a sentence like 'first second', only 'first' will be read. To read a full line, you should use fgets.
Try to avoid using gets, as it doesn't limit the number of characters to read, which could cause a security vulnerability.
You could also use scanf like
scanf("%99[^\n]", str);
It will read any non '\n' (line ending) character upto max 99 so your buffer won't overflow.
Although using fgets is a safer bet.
scanf will read until first whitespace ,so only first word will be stored in str.
use fgets instead of scanf:(using fgets is a safe way)
#include <stdio.h>
int main()
{
char str[100];
char* p;
printf("\nSentence: ");
fgets(str, 100, stdin);
p = str;
while (*p != '\0') {
if (*p == ' ') {
printf("\n");
}
else {
printf("%c", *p);
}
p++;
}
return 0;
}
Related
Hello I am doing a looping on my code with fgets and I want that when user introduces the word "bye" the program ends, so I have a do while like this:
char buf[1000]
do{
fgets(buf, 1000, stdin);
//More code here
while(strcmp(buf, "bye")!=0);
But I have a problem that it is, when user made a space or a tab or multiple spaces before write bye the strcmp doesnt recognize him as bye, so the program only exits when users only type bye without any previous space or tab.
I want to know how can I prevent the spaces or tabs before the by word to exits if user type for example:
' bye'
fgets reads in a complete line, including any starting white spaces and also including the new line character at the end of the line. Even if a user does not enter preceding white spaces, the content of buf is likely to be "bye\n", such that buf will hardly compare equal to "bye" when using strcmp.
I'd suggest to scan the buffer for a single word using sscanf and compare this word to "bye" then. Note that scanf("%s"...) skips white space characters at the beginning of a word and stops before the first white space after the word.
char isStopWord[20];
isStopWord[0] = '\0';
sscanf(buf,"%19s",isStopWord);
}
while(strcmp(isStopWord, "bye")!=0);
It a very strange requirement to use strcmp to remove characters from the array but everything is possible :)
char *removeSpacesAndTabsBeginning(char *str)
{
size_t len;
char savedc;
if(str && *str)
{
len = strlen(str);
savedc = str[1];
str[1] = 0;
while(!strcmp(str, " "))
{
str[1] = savedc;
memmove(str, str + 1, len);
savedc = str[1];
str[1] = 0;
}
str[1] = savedc;
}
return str;
}
int main(void)
{
char z[] = " \t\tHello World.";
printf("`%s`\n", removeSpacesAndTabsBeginning(z));
}
If you want to know if the string contains "bye" use strstr.
int isBye(const char *str)
{
return !!strstr(str, "bye");
}
There are 2 problems in your code:
you should test the return value of fgets() to detect unexpected end of file.
you should ignore whitespace in the comparison. You should just trim the string read by fgets() as the other code probably does not handle these either.
#include <ctype.h>
#include <stdio.h>
#include <string.h>
int main() {
char buf[1000];
while (fgets(buf, sizeof buf, stdin)) {
size_t i = 0, length = strlen(buf);
/* trim trailing white space */
while (length > 0 && isspace((unsigned char)buf[length - 1])) {
buf[--length] = '\0';
}
/* trim leading white space */
while (isspace((unsigned char)buf[i]) {
i++;
}
if (i > 0) {
memmove(buf, buf + i, length - i + 1);
}
// check for end command
if (!strcmp(buf, "bye"))
break;
//More code here: handle other commands
//...
}
return 0;
}
My output string needs to be palindrom of the input string. It works almost perfect but I am having problem with first character of the input string, my new string won't print it (in essence my new string won't print last character). Also strrev() does not work on Ubuntu so i need to do this without using that function.
#include <stdio.h>
#include <string.h>
int main(void){
int i,j=0;
char input_str[10];
char new_str[10];
printf("Enter characters:\n");
gets(input_str);
for(i=strlen(input_str)-1;i>0;i--){
new_str[j]=input_str[i];
j++;
}
printf("Output:\n");
printf("%s", new_str);
return 0;
}
For starters the function gets is unsafe function and is not supported by the C Standard.
You should use the standard C function fgets.
There are two problems with your code. The first one is in this loop
for(i=strlen(input_str)-1;i>0;i--){
new_str[j]=input_str[i];
j++;
}
the index i equal to 0 is skipped from using it to copy the corresponding character of the source string.
The second one is the destination array is not appended with the terminating zero character.
Here is a demonstrative program that shows how a function that makes a reversed copy of a source string can be implemented.
#include <stdio.h>
#include <string.h>
char * reverse_copy( char *dsn, const char *src )
{
size_t n = strlen( src );
size_t i = 0;
for ( ; i < n; i++ )
{
dsn[i] = src[n - i - 1];
}
dsn[i] = '\0';
return dsn;
}
int main(void)
{
enum { N = 10 };
char input_str[N] = "";
char new_str[N];
printf( "Enter a string (less than %zu symbols): ", ( size_t )N );
fgets( input_str, N, stdin );
input_str[ strcspn( input_str, "\n" ) ] = '\0';
printf( "\"%s\"\n", input_str );
printf( "\"%s\"\n", reverse_copy( new_str, input_str ) );
return 0;
}
The program output might look for example the following way
Enter a string (less than 10 symbols): Hello
"Hello"
"olleH"
i is never zero. That is why the first character (input_str[0]) is ignored.
I have created a function that reverses all the words in a sentence, meaning that if the input is "Hello World" the output is supposed to be "World Hello". The code below is the function.
char* reversesentence(char sent[]) {
int lth = strlen(sent);
int i;
for(i = lth -1; i >= 0; i--) {
if(sent[i] == ' ') {
sent[i] = '\0';
printf("%s ", &(sent[i]) + 1);
}
}
printf("%s", sent);
}
In the main I am trying to ask the user for the sentence and calling the function in the main.
int main(void)
{
char sentence[2000];
printf("Please enter the sentence you want to be reversed.\n");
scanf("%s", sentence);
reversesentence(sentence);
printf("%s", sentence);
}
It seems that the array is only storing the first word of the sentence only.
Output:
Please enter the sentence you want to be reversed.
hello my name is
hellohello
Process finished with exit code 0`
Can someone help me fix this please? Searched online and found nothing useful.
scanf stops reading when it occurs whitespace,tabs or newline.
Matches a sequence of non-white-space characters; the next pointer
must be a pointer to character array that is long enough to hold the
input sequence and the terminating null byte ('\0'), which is added
automatically. The input string stops at white space or at the maximum
field width, whichever occurs first.
Thus you are not reading the entire string as you input.
Try using fgets as below.
fgets(sentence, sizeof(sentence), stdin);
Note fgets appends \n to end of the string. see how to trim the
new line from
fgets
You have two problems
as it was already said you only read one word using scanf
reversesentence just replace all spaces by a null character, so even you read a full line you cut it at the first space. so if you enter "hello world" the result will be "hello", and if you enter " hello world" the result will be an empty string
The simple way is to read words using scanf in a loop until it returns EOF, memorizing them, to at the end produce the list of words returned
For instance :
#include <stdlib.h>
#include <string.h>
int main()
{
size_t len = 0;
char * result = 0;
char word[256];
while (scanf("%256s", word) != EOF) {
if (result == 0) {
result = strdup(word);
len = strlen(word);
}
else {
size_t l = strlen(word);
char * r = malloc(len + l + 2);
strcpy(r, word);
r[l] = ' ';
strcpy(r + l + 1, result);
free(result);
result = r;
len += l + 1;
}
}
puts(result);
free(result);
return 0;
}
The reading finishes at the end of the input (^d under a linux shell), the words can be given on several lines.
With the input
hello world
how
are you
?
that prints
? you are how world hello
Here is my code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int individualAverage(int data[][20],int j)
{
int k,average=0;
for(k=0;k<10;k++)
{
average += data[k][j];
}
return average;
}
int main()
{
int var,indAvg=0;
int i=0,j,k;
char *experiments[20];
int data[10][20];
char str[100],str2[100];
char *ptr, *token;
int no_line=1;
while(fgets(str,100,stdin) != NULL && (strcmp(str,"*** END ***") && strcmp(str,"*** END ***\n")))
{
if(no_line % 2 == 0)
{
k=0;
token = strtok (str," ");
while (token != NULL)
{
sscanf (token, "%d", &var);
data[k++][i] = var;
token = strtok (NULL," ");
}
i++;
}
else
{
ptr = strdup(str);
experiments[i] = ptr;
}
no_line++;
}
fgets(str,100,stdin);
token = strtok(str," ");
while(token != NULL && (strcmp(token,"4") && strcmp(token,"4")))
{
sscanf (token, "%d", &var);
printf("DATA SET ANALYSIS\n1.\tShow all the data\n2.\tCalculate the average for an experiment\n3.\tCalculate the average across all experiments\n4.\tQuit\nSelection: %d\n\n",var);
switch(var)
{
case 1 :
for(j=0;j<i;j++)
{
printf("%s",experiments[j]);
for(k=0;k<10;k++)
{
printf("%d ",data[k][j]);
}
printf("\n");
}
printf("\n");
break;
case 2 :
printf("What experiment would you like to use?\n");
token = strtok (NULL," ");
sscanf (token, "%s", &str);
for(j=0;j<i;j++)
{
if(strcmp(experiments[j],str) == 0)
{
indAvg = individualAverage(data,j);
printf("Experiment: %s",experiments[j]);
printf("The individual average of the experiment is %d\n",indAvg);
break;
}
}
}
token = strtok(NULL," ");
}
}
OK, so I have a method that takes lines of redirection input. The lines come in pairs. First line is the name of an experiment, and the second line has the 10 values separated by spaces for that experiment. After these pairs, there is an ending line "*** END ***"
After this line, there is one last line holding the instructions of what to do with the data.
I'm currently having a problem where I've used fgets() to store the strings of the first pairs of lines into a variable which I declared as char *experiments[20];
Each of strings that this array is pointing to will have '\n' at the end of the string because of fgets()
Back to the last line of instructions. You have values 1-4. Right now I'm looking at instruction 2. It tells the average of an experiment. So after 2 on the last line, there must be the name of one of the experiments. I've used:
char str[100];
int var;
char *token;
token = strtok(str, " ");
sscanf (token, "%d", &var);
to get the first value on the line into var (pretend it's 2). So after that would be a string. Say it's Test 1, I'll use
token = strtok (NULL," ");
sscanf (token, "%s", &str);
to get the value into str, and then I'll compare it to experiments for all possible indexes.
HOWEVER, because fgets() gives '\n' at the end of the lines, all of the experiments strings will have '\n' at the end while str will just have the name of the experiment WITHOUT '\n' therefore they will never be equal even if '\n' is the only difference between the strings.
Any solutions?
Since you know that there may be a \n at the end of the string, you could check for it, and remove it if it's there:
size_t len = strlen(str);
if (len != 0 && str[len-1] == '\n') {
str[len-1] = '\0';
}
This would terminate the line at \n, so your strcmp would succeed. An alternative is to use strncmp, and pass the length of the target string. This runs the risk of false positives when there's a longer suffix that \n, though.
You could also read your data like this:
fscanf(f, "%99[^\n]", str);
You can make your own version of fgets that doesn't store the new-line character when it encounters one, and call it myfgets. Something like this would replicate fgets's behaviour, I think, produced with respect to the description given in MSDN:
char * myfgets( char * str, int n, FILE * stream ) {
if ( n <= 0 ) return NULL; // won't accept less than or equal to zero length
int currentPos = 0;
while ( n-- > 0 ) {
int currentChar = fgetc( stream );
if ( currentChar == EOF ) return NULL;
if ( currentChar == '\n' ) break;
// if these two lines were in reversed order,
// it would behave same as the original fgets
str[currentPos++] = currentChar;
}
return str;
}
But of course the other solution is simpler, hehe...
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);
}