fgets() and sscanf() only stores first integer in array [closed] - c

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 3 years ago.
Improve this question
I was trying to terminate Integer array input using Enter key. So, I thought of using fgets and sscanf() but I have tried several approaches everytime i am getting first value only. Can someone help where I am doing wrong.
#include<stdio.h>
int main(){
int inp[100]={0};
int c=0,n;
char str[100]={0};
char *data = str;
while ((NULL != fgets(str, sizeof str, stdin)) && (str[0] != '\n')) {
if (1 != sscanf(str,"%d",&inp[c])) {
puts("Input was not an integer, try again.\n");
continue;
}
printf("\ninp[%d] = %d",c,inp[c]);
c++;
if (c >= 100) break;
}
}
I have added snap of my code and output -
Code
Output

%n is to capture the how many bytes have been read, thus you need to increment data n bytes to point to next number.
The below program reads all the integers till empty new line.
int main() {
int inp[100] = {0};
int c = 0, n = 0;
char str[100] = {0};
char *data = str;
while ((NULL != fgets(str, sizeof str, stdin)) && (str[0] != '\n')) {
data = str;
n = 0;
while (1 == sscanf(data, "%d%n", &inp[c], &n) && c < 100) {
printf("\ninp[%d] = %d\n", c, inp[c]);
data += n;
c++;
}
}

Related

A function to check if the word has an increasing or decreasing sequence of chars in C [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 2 years ago.
Improve this question
I'm new in C.
I've been asked to write a function that checks if the string has increasing/decreasing sequence of letters based on ASCII values + not includes white spaces(tabs,new lines etc.).
For example: demo is a very increasing string
beef is an increasing string
aa or zzz is an increasing string
tonic is a very decreasing string
spoon is a decreasing string
suddenly has no clear sequence.
So I wrote this code,it works but not so well..can you help me to improve it a little bit?
#include <stdio.h>
void f_sequence (char str[]);
int main()
{
char strl[101];
printf("your string is:\n");
scanf("%s\n", strl);
f_sequence(strl);
return 0;
}
void f_sequence(char str[])
{
int increase=0;
int decrease=0;
int match=0;
int i = 1;
if(!str[0])
printf("empty");
else if(!str[1])
printf("need more chars");
for(i=1; str[i]; i++)
{
if (str[i] == str[i-1])
match = 1;
if (str[i] > str[i-1])
increase = 1;
if (str[i] < str[i-1])
decrease = 1;
}
if((decrease==1) && (increase==0) && (match==0))
printf("we have a very descreasing sequence in here");
if((decrease==0) && (increase==1) && (match==0))
printf("we have a very increasing sequence in here");
if((decrease==1) && (increase==0) && (match==1))
printf("we have a descreasing sequence in here");
if((decrease==0) && (increase==1) && (match==1))
printf("we have an increasing sequence in here");
if((decrease==0) && (increase==0) && (match==1))
printf("we have an increasing sequence in here");
if((decrease==1) && (increase==1))
printf("not increasing and not decreasing");
puts("");
}
To ignore whitespaces, you can use isspace from <ctype.h> and skip in your calculations:
for(i = 1; str[i]; i++)
{
if (isspace((unsigned char)str[i])) continue;
...
}
But as is, you can't read input string with whitespaces as scanf with %s would stop reading at the first whitespace. You need fgets to read a line (so that you could read a string with whitespaces):
int main()
{
char strl[101];
printf("your string is:\n");
if (fgets(strl, sizeof strl, stdin)) {
char *p = strchr(strl, '\n');
if (p) *p = '\0'; // Remove newline if present
f_sequence(strl);
}
}
fgets would also read the newline character if there's space in the buffer which you may want to remove as shown (include <string.h> for strchr).
Use a function like below to remove whitespaces:
void removeSpaces(char *str)
{
// To keep track of non-space character count
int count = 0;
// Traverse the given string. If current character
// is not space, then place it at index 'count++'
for (int i = 0; str[i]; i++)
if (str[i] != ' ')
str[count++] = str[i]; // here count is
// incremented
str[count] = '\0';
}
And then add this function in the first line of f_sequence function. like this:
removeSpaces(str);

C programming: strlcpy with len = 0 [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 4 years ago.
Improve this question
I'm just learning about programming using the C language.
Today, I'm trying to code my own strlcpy function and I am facing a problem.
To test my function I compare the results with the "official" function's ones. Everything works fine except... When I put 0 as the len arg.
The strcpy function seems to put a garbage character in the destination string and I really don't understand why.
Here is the function's prototype:
size_t strlcpy(char * restrict dst, const char * restrict src, size_t dstsize);
Thanks for your help!
Ok. I wanted to make a lot of tests, this is the reason why I'm calling the function inside of a loop.
Here is a part of my main function, testing the function:
do
{
/* Ask for first string */
printf("\nGive me a string (0 to stop): ");
gets(str);
/* Ask for a number */
printf("Now, give me a number please: ");
scanf("%d", &i);
while (getchar() != '\n');
/* I test with the "official function */
j = strlcpy(str2, str, i);
printf("Here is the expected result: %s\n", str2);
printf("Num returned: %d\n", j);
/* Now I test using my function */
j = ft_strlcpy(str3, str, i);
printf("Here is my result: %s\n", str3);
printf("Num returned: %d\n", j);
}while (str[0] != '0');
And here is the function I've coded:
unsigned int ft_strlcpy(char *dest, char *src, unsigned int size)
{
unsigned int cpt;
unsigned int i;
cpt = 0;
i = 0;
while (src[cpt] != '\0')
cpt++;
if (size == 0)
return (0);
while (i < cpt && i < (size - 1))
{
dest[i] = src[i];
i++;
}
dest[i] = '\0';
return (cpt);
}
In the function I'm not supposed to call any function from the standard library. My main is just here for testing.
The function prototype is given by my teacher, this is the reason why I don't respect the original one.
Sorry fort the time I needed to put my code here and thank you for your help.
could you explain me where the "garbage character" comes from? What does the function do to find this character and to put it in the string? Even if it is not supposed to be called with a 0 len value.
The manual does not say that strlcpy is not supposed to be called with a 0 len value, it only says that it isn't NUL-terminating the result if dstsize is 0, i. e. it copies no characters at all to dst.
Your impression that it would put a "garbage character" into the destination string most probably results from dst being uninitialized from the start, and you looking at the unchanged, uninitialized dst.
First of all, I suppose you mistype in "...strlen function seems to put a garbage..." (strlcpy should be instead of strlen, because strlen put nothing to string - size_t strlen(const char *s);).
So you have a question about strlcpy.
As referencess said about the third argument of strlcpy (as well as strncpy) determies number of characters to be copied from src to dst. So, in case of 0-size no data should be copied. Read documentation carefully - prototype is:
strlcpy(char *dst, const char *src, size_t size);
and explanation for size has words:
as long as size is larger than 0
There are several issues in your program.
First of all don't use gets(). It's not safe and moreover it has been obsoleted. Check this.
Instead use fgets(). Check this.
In this statement
printf("\nGive me a string (0 to stop): ");
0 to stop will actually not stop anything and execute all the statements below it until while loop checks the condition. May you want a put if condition, like this:
if (str[0] != '0') {
.....
.....
}
}while (str[0] != '0');
In this statement
printf("Now, give me a number please: ");
scanf("%d", &i);
....
....
j = ft_strlcpy(str3, str, i);
You are passing this number as the destination size to your ft_strlcpy() function. Assume your source string contains "123456789" string and destination string size is 5 and user has given number input as 100. In function ft_strlcpy(), for the given input
//cpt variable value would be 9
//size variable value would be 100
//initial value of i is 0
while (i < 9 && i < (100 - 1))
{
dest[i] = src[i]; //buffer overflow!!!!, this statement will execute 9 times and dest buffer size is 5
i++;
}
So, instead of taking the number of characters to be copy as input from user, you should give size of the destination buffer. Like this
j = ft_strlcpy(str3, str, sizeof(str3));
From strlcpy
strlcpy() copies up to dstsize - 1 characters from the string src to dst,
NUL-terminating the result if dstsize is not 0.
That means if destination buffer size is 0, no copy is performed.
Check this also.
Putting these all together, you can do:
#include <stdio.h>
#include <string.h>
unsigned int ft_strlcpy(char *dest, const char *src, unsigned int size) {
unsigned int i = 0, j = 0;
while (src[i] != '\0') {
if (size && (i < (size - 1))) {
dest[i] = src[i];
j++;
}
i++;
}
dest[j] = '\0';
return (i);
}
int main() {
char str[100], str3[100];
unsigned int j;
do {
/* Ask for first string */
printf("\nEnter a string (press only enter key to stop): ");
if (fgets(str, sizeof(str), stdin) == NULL) {
fprintf (stderr, "Failed to read input");
break;
}
/* If input is bigger than the size of buffer, discard the rest of input characters */
if (strchr(str, '\n') == NULL) {
int c;
while((c = getchar()) != '\n' && c != EOF)
/* discard the character */;
}
else {
/* Remove the trailing newline character */
str[strcspn(str, "\n")] = 0;
}
if (str[0] != '\0') {
j = ft_strlcpy(str3, str, sizeof(str3));
printf("Here is my result: %s\n", str3);
printf("Num returned: %d\n", j);
}
}while (str[0] != '\0');
return 0;
}

Multiplying the numbers of a String [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
I want to multiply the numbers in a given string which has one or more spaces.
Example:
If i input 52 26 23
the output should be 31096.
I've written this code but its not working:
#include <stdio.h>
int main()
{
char input[30];
int i, num = 0, v = 1;
gets(input);
for (i = 0; input[i] != '\0'; i++)
{
if(input[i] == 32)
{
v = v * num;
if(input[i+1] != 32)
{
num = 0;
continue;
}
}
num = (num * 10) + (input[i] - 48);
}
printf("%d",v);
return 0;
}
Try this one
#include <stdio.h>
#include <string.h>
int main()
{
char str[30];
char *token;
long int mul = 1;
gets(str);
token = strtok(str, " ");
while (token != NULL)
{
mul = mul * atoi(token);
token = strtok(NULL, " ");
}
printf("%ld",mul);
return 0;
}
The problem lies in your nested if statement. Once it enters the first if statement, that means input[i]==32, therefore it can never enter the next if statement where input[i]!=32.
I also have some suggestions for improving readability. Instead of using numbers to represent the characters, use the character literals themselves!
Another thing, you only have space for 30 characters in your input buffer. If a user attempts to enter more than this, you will have a buffer overflow.
Lastly, if the user puts more than one space between numbers, the output will become 0. That may be something you may or may not want to handle.
Edit: Before, the call to gets was only grabbing characters up to the first whitespace character. I've fixed this issue with a format string in a call to scanf instead. Buffer overflow problem still applies. Also, it was not multiplying with the last parsed integer, so I added code for that after the loop. Another note, this will only work for non-negative integers, if that's something you weren't aware of initially. The code just assumes the input is nice.
Edit 2: support for input with any number of spaces before, between, or after inputs.
#include <stdio.h>
int main() {
char input[30];
int i, num = 0, v = 1;
scanf("%[^\n]s", input);
// skip leading spaces
for(i = 0; input[i] == ' '; i++);
// parse remaining input
while(input[i] != '\0') {
if(input[i] == ' ') {
v *= num;
num = 0;
// skip subsequent spaces
while(input[++i] == ' ');
continue;
}
num *= 10;
num += input[i] - '0';
i++;
}
// ignore trailing spaces
if(input[i - 1] != ' ') {
// get last parsed integer
v *= num;
}
printf("%i\n", v);
return 0;
}

I've got an issue with my Enigma simulation [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
void character(){
int i=0;
char c;
printf("type your text to encode (max 80 chars):\n");
while((c=getchar()) != '\n')
{
text[i] = toupper(c);
i++;
}
text[i] = '\0';}
I'm using this piece of code in an emulator of Enigma. My problem is that the While instruction is always jumped, and I can't understand what's the problem and how to fix it!
Maybe there is something wrong with the declaration of the array text. This solution could clarify your question.
#include <stdio.h>
#include <ctype.h>
#define MAX_SIZE 10
int main(void) {
char text[MAX_SIZE];
int i = 0;
int c;
while ((c = getchar()) != '\n' && i <= MAX_SIZE - 2) {
text[i] = toupper(c);
i++;
}
text[i] = '\0';
printf("%s\n", text);
return 0;
}
As #trentcl mentioned, if there is a scanf prior to calling character() there is probably a newline left in the input stream. This will test for a leading newline and continue the loop.
The #define will set the size of the array so the loop does not put too many characters into text.
#define LIMIT 256
char text[LIMIT + 1] = {'\0'};
void character(){
int i = 0;
int c;
printf ( "type your text to encode (max 80 chars):\n");
while ( ( c = getchar ( )) != EOF)
{
if c == '\n') {
if ( i) {
break;//trailing newline
}
else {
continue;//leading newline
}
}
text[i] = toupper ( c);
i++;
if ( i >= LIMIT) {
break;
}
}
text[i] = '\0';
}

Reverse the order of an integer in C [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 7 years ago.
Improve this question
I am currently learning C as part of a course and I have a task to reverse the order of a number without using any arithmetic (wording of the task).
I currently have this:
#include <stdio.h>
int main()
{
int n, reverse = 0;
printf("Enter a number to reverse\n");
scanf("%d", &n);
while (n != 0) {
reverse = reverse * 10;
reverse = reverse + n_10;
n = n / 10;
}
printf("Reverse of entered number is = %d\n", reverse);
return 0;
}
But this solution uses arithmetic. How can I alter this to complete the task?
From the exercise sheet, "though even at three
digits the naïve approach quickly grows unmanageable with arithmetic (try it!).
Your goal: Design 3-digit solution without using any arithmetic.(Hint: use scanf.)"
The wording of the question was confusing but to be clear the question is:
How do you reverse the order of a number, e.g. 123456789 to 987654321, without without using math. So the solution is to scanf to read the number and swap the numbers in a loop as the answer below.
You can just read it in as a string.
int main()
{
char str[80];
fgets(str, 80, stdin);
strrev(str);
printf("%s\n", str);
}
void strrev(char *str)
{
char *end, tmp;
end = str + strlen(str) - 1;
for (; end > str; --end, ++str) {
tmp = *end;
*end = *str;
*str = tmp;
}
}
I don't know if you consider pointer arithmetic to be "arithmetic"
Read as series of short strings that can hold 1 digit and then print in the reserve order.
char buf[10][2] = { 0 };
scanf("%1[0-9]%1[0-9]%1[0-9]%1[0-9]%1[0-9]%1[0-9]%1[0-9]%1[0-9]%1[0-9]%1[0-9]",
&buf[0], &buf[1], &buf[2], &buf[3], &buf[4],
&buf[5], &buf[6], &buf[7], &buf[8], &buf[9]);
printf("%s%s%s%s%s%s%s%s%s%s",
buf[9], buf[8], buf[7], buf[6], buf[5],
buf[4], buf[3], buf[2], buf[1], buf[0]);
Obviously limited to max 10 digits.
A recusive approach, inpsired by #Nisse Engström. Works for any reasonable length input.
void pr(void) {
char digit[2];
if (scanf("%1[0-9]",digit)) {
pr();
printf("%s",digit);
}
}
int main(void) {
pr();
return 0;
}
Input
012345678901234567890123456789
Output
987654321098765432109876543210
Of course if (scanf("%1[0-9]",digit)) { should be if (scanf("%1[0-9]",digit) == 1) { to cope with EOF but that then may be "arithmetic".
Using scanf():
int
scanf (){
int
stdin =
getchar ();
return
stdin <0||
stdin ==
'\n'?
stdin :(
scanf (),
putchar (
stdin )),
'\n';}
int
main (){
putchar (
scanf ()
);}
Read integer, use sprintf() function to convert it into string and then use the library function strrev() to reverse the string.

Resources