How does sscanf() see numbers in a string? - c

I have a problem with sscanf() in the following code:
void num_check(const char*ps){
char *ps1=NULL;
int number=0;
unsigned sum_num=0;
ps1=ps;
for(;*ps1!='\0';ps1++){
if (isdigit(*ps1)){
sscanf(ps1,"%d",&number);
sum_num+=number;
}
}
printf("Sum of digits is: %d",sum_num);
}
int main(){
printf("Enter a string:\n");
char str[20];
gets(str);
num_check(str);
return 0;
}
The problem is: when I input a string in the form of "w2b4e" it sums my numbers OK, and I get the desired result. But when I try to input a string such as "w23b4e", what it does is: it sees the number 23 in the loop, so variable number=23, and sum_num=23, but the next step in the loop is this: number=3, and sum_num=26. And in the next step sum_num= 30...
This confuses me quite a bit. Since I don't believe that sscanf() has such a quirky flaw, what am I doing wrong?

You always advance by exactly one character in the loop: ps1++. You probably want to advance ps1 to the first digit instead.
Better yet, there's a function called strtol. It tries to parse integers from strings and can return the position of the first character that could not be read. So you can use strtol in a loop to sum everything that looks like a number in your string.
If you want to sum digits instead of numbers found in a string, it's easier:
while (*p) {
if (isdigit(*p))
sum_num += *p - '0';
}

If you want to sum digits (not the whole number), use the following instead:
if( isdigit(*ps1)) {
sum_num += *ps1 - '0';
}
You can also use sscanf("%1d", ps1) to make it read only one character.

for(;*ps1!='\0';ps1++){
if (isdigit(*ps1)){
sscanf(ps1,"%d",&number);
sum_num+=number;
}
}
you are incrementing ps1 one character at a time, independently of how many digits are being read. Unfortunately you cannot use sscanf for this task, since you are not able to know how many characters have been read.

sscanf works like it should, it doesn't move beginning of pointer, you are moving it by one character in for loop.

Related

What is wrong with the program?

I'm extremely new to C and am doing a few problems I found in a book I bought. What is wrong with this program?
int main (void)
{
char text[50]='\0';
scanf ("%s", text);
printf("%c", text[49]);
printf("%s", text);
return 0;
}
char text[50]='\0';
is not valid. You could skip initialising text and just declare it
char text[50];
or you could initialise its first element
char text[50]={'\0'};
You're also missing an include of stdio.h and should really check that your scanf call read a string and could give it a max length for the string
if (scanf("%49s", text) == 1)
You want to get rid of:
printf("%c", text[49]);
as you have no idea what's at that memory location if the string is less than 49 chars long.
There is a difference of single quotes and double quotes in C.
double quotes means string
single quotes means character
Line 3 will not compile because the compiler wants you to assign a string to the array of characters.
You can do
char text[50]="\0";
which in effect fills all the 50 bytes with zeros.
You could also do
char text[50]="bla";
which fills the first 3 bytes with "bla" and the rest with zeros. At least my compiler does it like that.
You could also do nothing because you anyway fill it with user input just the next statement.
char text[50];
scanf ("%s", text);
But then you have a problem. Because the very next statement will give you random output if the user has entered a string with less than 49 characters. But if you initialize, well then you output the zero byte, which is also quite useless.
The main point however is to learn the different behaviour of C when dealing with an array of characters.
int main ()
{
char text[50]={'1','2','3','4'};
printf("%c", text[1]);
printf("%c",text[0]);
getch();
return 0;
}
do like this..

swapping string in c using pointer

Need help
this is my code
void swapstringfun()
{
int i=0,j=0;
char *str=(char *)malloc(sizeof(char)*15);
char *mystr=(char *)malloc(sizeof(char)*15);
system("cls");
printf("Please enter first string :\t");
scanf("%s",str);
printf("Please enter second string :\t");
scanf("%s",mystr);
while(*(str+i)!='\0' && *(mystr+i)!='\0')
{
*(str+i) ^=*(mystr+i);
*(mystr+i) ^=*(str+i);
*(str+i) ^=*(mystr+i);
i++;
}
printf("%s swapped to %s",str,mystr);
getch();
main();
}
I wrote the above code to swap the string using XOR operator. The problem with this code is. when my input is lets say.. RAJESH and ASHISH. Then, it shows output ASHISH and RAJESH. And, that is expected.
But, when input is let say.. ABHISHEK and CODER .Then, output is CODERHEK and ABHIS. But, the expected output is CODER and ABHISHEK. Anyone help me to solve this problem. I will appreciate.
You iterate and swap until you reach the end of the shorter string
while(*(str+i)!='\0' && *(mystr+i)!='\0')
(or both, if the lengths are equal). To iterate until you reach the end of the longer string, you need an || instead of the && and be sure that 1. both pointers point to large enough memory blocks, and 2. the shorter string ends with enough 0 bytes. So you should calloc the memory, not malloc.
However, you should swap the pointers, really,
char *tmp = str;
str = mystr;
mystr = tmp;
You also need to swap the terminating 0, as its part of what is called a string in C.
The 0 is the stopper element in the character array, describing the string.
You need to XOR the entire length of both strings. Since in your second example, the strings are different lengths, your algorithm won't work.
This is the statement you'll have to reconsider:
while(*(str+i)!='\0' && *(mystr+i)!='\0')

counting the number of digits in using only scanf in c

I need to limit the input from a user to only positive values, and count the number of digits in that number. The user will only type in a (+/-) whole number up to 9 characters long.
I'm only allowed to use the scanf function and for, while, or do-while loops.(I saw in similar questions how to do this using getchar, but I can only use scanf). I'm not allowed to use arrays, or any other library besides stdio.h and math.h
I know that if I write:
n=scanf("%c%c%c%c%c",&a,&b,&c,&e,&f);
n will count the number of successful scanf conversions.
The problem i'm having is that when I define the input with char, it does everything I want except that the user MUST enter 5 characters. So if the user wants to input "55" he has to press "5" "5" "enter" "enter" "enter".
I need the program to move on after the first "enter" but also be flexible to receive a number up to 9 digits long.
again, I can't use getchar or anything fancy. Just the really basic stuff in C that you learn in the first 2 weeks.
Use scanf to read the number into a long int , then use a for loop with a /10 to count the number of digits
What do you want the program to do in case of a -ve number being entered?
#include<stdio.h>
int main()
{
long int a;
int b;
do
{
scanf ("%ld",&a);
if(a<0)
printf ("invalid input");
}while(a<0);
for(b=0;a!=0;b++,a=a/10);
printf("%d",b);
}
(does not handle -ve numbers specially)
Something like
#include <stdio.h>
int main(void)
{
char buffer[10] = { 0 };
size_t len;
scanf("%9[0-9]", buffer);
for(len = 0; buffer[len] != 0; len++) ;
printf("%zu '%s'\n", len, buffer);
return 0;
}
works, but I don't know if it fits your need.
EDIT (bits of explanation)
You can replace size_t with int (or unsigned int), though size_t is better. If you do, use %d or %u instead of %zu.
The basic idea is to exploit a feature of the format of scanf; the 9[0-9] says the input is a sequence of up to 9 char in the given set i.e. the digits from 0 to 9.
The for(...) is just a way to count char, a simple implementation of a strlen. Then we print the result.
The approach I would take would be the following.
Loops are allowed, so go ahead and set one up.
You need to have a variable somewhere that will keep track of what the current number is.
Think about typing out a number, one character at a time. What needs to happen to the current_number variable?
You need to stop the loop if a return key has been pressed.
Something like this should do for starters, but I'll leave the rest up to you, specifically what return_check(ch), update_state(current_val) and char_to_int(ch) looks like. Also note that rather than use a function, feel free to put your own function directly into the code.
int current_val=0;
int num_digits=0;
char ch="\0"
for (num_digits=0;return_check(ch) && num_digits<=9;num_digits++)
{
fscanf("%c");
current_val=update_state(current_val);
current_val=current_val+char_to_int(ch);
}
As for the logic in update_state(), think about what happens, one character at a time, if a user types in a number, like 123456789. How is current_val different from a 1 to a 12, and a 12 to a 123.
Can you wrap a loop around it, something like (I don't know if all of the syntax is right):
const int max_size=9
int n=0; //counter for number of chars entered
char a[max_size-1];
do {
scanf(%c,&a[n]);
n++;
} while (a[n] != '\r' && n<max_size)

C homework - string loops replacements

I know it's a little unorthodox and will probably cost me some downvotes, but since it's due in 1 hour and I have no idea where to begin I thought I'd ask you guys.
Basically I'm presented with a string that contains placeholders in + form, for example:
1+2+5
I have to create a function to print out all the possibilities of placing different combinations of any given series of digits. I.e. for the series:
[9,8,6] // string array
The output will be
16265
16285
16295
18265
18285
18295
19265
19285
19295
So for each input I get (number of digits)^(number of placeholders) lines of output.
Digits are 0-9 and the maximum form of the digits string is [0,1,2,3,4,5,6,7,8,9].
The original string can have many placeholders (as you'd expect the output can get VERY lengthly).
I have to do it in C, preferably with no recursion. Again I really appreciate any help, couldn't be more thankful right now.
If you can offer an idea, a simplified way to look at solving this, even in a different language or recursively, it'd still be ok, I could use a general concept and move on from there.
It prints them in different order, but it does not matter. and it's not recursive.
#include <stdlib.h>
#include <stdio.h>
int // 0 if no more.
get_string(char* s, const char* spare_chr, int spare_cnt, int comb_num){
for (; *s; s++){
if (*s != '+') continue;
*s = spare_chr[comb_num % spare_cnt];
comb_num /= spare_cnt;
};
return !comb_num;
};
int main(){
const char* spare_str = "986";
int num = 0;
while (1){
char str[] = "1+2+5";
if (!get_string(str, spare_str, strlen(spare_str), num++))
break; // done
printf("str num %2d: %s\n", num, str);
};
return 0;
};
In order to do the actual replacement, you can use strchr to find the first occurrence of a character and return a char * pointer to it. You can then simply change that pointer's value and bam, you've done a character replacement.
Because strchr searches for the first occurrence (before a null terminator), you can use it repeatedly for every value you want to replace.
The loop's a little trickier, but let's see what you make of this.

Splitting a string in C into separate parts

I've been trying to write a function in C that detects palindromes. The program currently looks like the following:
#include <stdio.h>
#include <string.h>
int main()
{
char palindrome[24]; int palength; int halflength;
gets(palindrome);
palength = strlen(palindrome);
halflength = palength / 2;
printf("That string is %u characters long.\r\n", palength);
printf("Half of that is %u.\r\n", halflength);
return 0;
}
Right now it detects the length of a string, and also shows what half of that is. This is just to make sure it is working how I think it should be. What the rest of the function should do (if possible) is take the integer from "halflength" and use that to take that amount of characters off of the beginning and end of the string and store those in separate strings. From there I'd be able to compare the characters in those, and be able return true or false if the string is indeed a palindrome.
TL;DR - Is it possible take a certain amount of characters (in this case the integer "halflength") off the front and end of a string and store them in separate variables. Read above for more information on what I'm trying to do.
P.S. - I know not to use gets(), but didn't feel like writing a function to truncate \n off of fgets().
int len = strlen(palindrome) - 1; // assuming no \n
int half = len << 1;
for (int i=0; i<=half; ++i)
if(palindrome[i] != palindrome[len-i])
return false;
return true;
What if you do something like this,
char *str1="lol",*str2;
str2=strrev(str1);
//if both are same then it actually is a palindrome ; )
Found out I was approaching the problem wrong. How I should be doing this is iterating over the characters using a pointer both backwards and forwards. Although if you'd still like to answer the original question it could still be useful at some point.

Resources