Say I have a string like ab234cid*(s349*(20kd and I want to extract all the numbers 234, 349, 20, what should I do ?
You can do it with strtol, like this:
char *str = "ab234cid*(s349*(20kd", *p = str;
while (*p) { // While there are more characters to process...
if ( isdigit(*p) || ( (*p=='-'||*p=='+') && isdigit(*(p+1)) )) {
// Found a number
long val = strtol(p, &p, 10); // Read number
printf("%ld\n", val); // and print it.
} else {
// Otherwise, move on to the next character.
p++;
}
}
Link to ideone.
A possible solution using sscanf() and scan sets:
const char* s = "ab234cid*(s349*(20kd";
int i1, i2, i3;
if (3 == sscanf(s,
"%*[^0123456789]%d%*[^0123456789]%d%*[^0123456789]%d",
&i1,
&i2,
&i3))
{
printf("%d %d %d\n", i1, i2, i3);
}
where %*[^0123456789] means ignore input until a digit is found. See demo at http://ideone.com/2hB4UW .
Or, if the number of numbers is unknown you can use %n specifier to record the last position read in the buffer:
const char* s = "ab234cid*(s349*(20kd";
int total_n = 0;
int n;
int i;
while (1 == sscanf(s + total_n, "%*[^0123456789]%d%n", &i, &n))
{
total_n += n;
printf("%d\n", i);
}
here after a simple solution using sscanf:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
char str[256]="ab234cid*(s349*(20kd";
char tmp[256];
int main()
{
int x;
tmp[0]='\0';
while (sscanf(str,"%[^0123456789]%s",tmp,str)>1||sscanf(str,"%d%s",&x,str))
{
if (tmp[0]=='\0')
{
printf("%d\r\n",x);
}
tmp[0]='\0';
}
}
Make a state machine that operates on one basic principle: is the current character a number.
When transitioning from non-digit to digit, you initialize your current_number := number.
when transitioning from digit to digit, you "shift" the new digit in:
current_number := current_number * 10 + number;
when transitioning from digit to non-digit, you output the current_number
when from non-digit to non-digit, you do nothing.
Optimizations are possible.
If the numbers are seprated by whitespace in the string then you can use sscanf(). Since, it's not the case with your example,
you have to do it yourself:
char tmp[256];
for(i=0;str[i];i++)
{
j=0;
while(str[i]>='0' && str[i]<='9')
{
tmp[j]=str[i];
i++;
j++;
}
tmp[j]=0;
printf("%ld", strtol(tmp, &tmp, 10));
// Or store in an integer array
}
#include<stdio.h>
#include<ctype.h>
#include<stdlib.h>
void main(int argc,char *argv[])
{
char *str ="ab234cid*(s349*(20kd", *ptr = str;
while (*ptr) { // While there are more characters to process...
if ( isdigit(*ptr) ) {
// Found a number
int val = (int)strtol(ptr,&ptr, 10); // Read number
printf("%d\n", val); // and print it.
} else {
// Otherwise, move on to the next character.
ptr++;
}
}
}
Or you can make a simple function like this:
// Provided 'c' is only a numeric character
int parseInt (char c) {
return c - '0';
}
Related
How to use isdigit function in C to check whether the given multiple digit string is numeric or not?
This is how I used isdigit function for a single digit character.
#include<stdio.h>
#include<cs50.h>
#include<ctype.h>
int main()
{
char c = get_char("Enter a single character:");
int a = isdigit(c);
if ( a != 0)
{
printf("%c is an integer \n", c);
}
else
{
printf("%c is not an integer \n",c);
}
}
Now, I want to check for the multiple digit character(eg. 92, 789). here is my code
#include<stdio.h>
#include<cs50.h>
#include<string.h>
#include<ctype.h>
int main()
{
string num = get_string(" Enter a number:");
int final = 1;
for(int i =0; i< strlen(num); i++)
{
// final = final * isdigit(num(i));
final*= isdigit(num[i]);
}
if(final!=0)
{
printf("%s is an integer.\n", num);
}
else
{
printf("%s is not an integer.\n", num);
}
}
However, the above code only works for two digit integer , but not for 3 digit integer. See this:
Compiled Code SS
The isdigit function isn't required to return a boolean 0 or 1 value. It's specified to return zero if the character isn't a digit, and any non-zero value if it is a digit.
Take for example the implementation used by here. We can see that isdigit returns 2048.
Because it returns that value, the multiplication will lead to a signed integer arithmetic overflow, which in turn leads to undefined behavior.
Instead I suggest you use isdigit directly in a condition, and if it returns 0 then print the message and terminate the program:
size_t length = strlen(num);
if (length == 0)
{
printf("String is empty\n");
return EXIT_FAILURE;
}
for (size_t i = 0; i < length; ++i)
{
if (isdigit(num[i]) == 0)
{
printf("Input was not a number\n");
return EXIT_FAILURE;
}
}
// Here we know that all characters in the input are digits
You could simply replace the multiply operation with &... Once a non-digit appears and isdigit() returns 0 (meaning false), the flag variable will remain false.
You may want to consider combining operations into compact code such as the following.
#include <stdio.h>
#include <ctype.h>
#include <cs50.h> // less "generic" that the others
int main( void ) {
string num = get_string(" Enter a number:");
int i = 0;
while( isdigit( num[i] ) ) i++; // loop fails on '\0', too
if( i == 0 || num[i] ) // empty string or did not reach its end
printf( "%s is NOT an integer.\n", num );
else
printf( "%s is an integer.\n", num );
return 0;
}
I'm trying to write an ITOA (integer to array) function using pointers.
So this is what I got so far. I debugged and it works just fine. The thing is, the printing itself doesn't work. I'm adding two screenshots.
Would appreciate some help.
int num_length(int number)
{
int count = 0;
while (number > 0)
{
count++;
number /= 10;
}
return count;
}
void itoa(int number, char *strptr)
{
int number_len = num_length(number);
char *start = strptr;
strptr += number_len - 1;
while (strptr >= start)
{
*strptr = number % 10;
number /= 10;
strptr--;
}
}
void print_string(char *strptr)
{
while (*strptr != '\0')
{
printf("%c", *strptr);
strptr++;
}
}
void main(void)
{
int number;
char number_in_string[N] = { '\0' };
char *strptr = &(number_in_string[0]);
printf("Enter a number: ");
scanf_s("%d", &number);
itoa(number, strptr);
print_string(number_in_string);
getch();
}
If you're trying to get an array of numeric characters (as seems evident by your print_string(a) function), you'll need to adjust the values appropriately:
*strptr = number % 10 + '0';
As per your debugging output ('\x2', '\x5', '\x5') , you're correctly getting the individual digits of the number but those are binary values, not the character representations.
Turning the former into the latter involves adding '0' (0x30 if you're using ASCII, for example). C guarantees that the numeric values are contiguous so this is safe.
(a) ... which could, by the way, be replaced with a simple:
printf("%s", number_in_string);
in your main function.
I've been working on a hangman game for a class course and I'm almost done. However, I've stumbled upon a problem that I can't seem to fix.
First, the computer choose a random word from a text file, takes the lenght of that word and with that length creates a masked copy of the original word. Then the game start. The player types in letters and if the word is completed before he/she fails six times, he wins. Otherwise, he/she loose. I think the problem with my code is when I create my mask of the word chosen by the computer, but I'm not sure.
If I run the program it looks something like this:
Chosen word: strand (first control of word chosen by computer)
Chosen word: strand (second control to see if the same word is copied from the function to the string in the main)
Chosen word: monster (this is printed by the free() function. for some reason it's one word higher)
Chosen word: strand (third control is done before the lenght of the word is copied, in order to see if it's the right word being copied, which it is)
Wordlenght: 6 (control to see if the lenght matches the word, which it does)
Mask: _ _ _ _ _ _ N (ignore the spaces between the underscores, they are only there to make it easier to see. this is where i think the problem is, because of the extra character added in the end, the "N" in this case. the number of underscores match the number of letters which is good)
Mask: _ _ _ _ _ _ N (printed by the second free() function)
Then the actual game starts. Everything else works fine (if the player aborts or looses and if the player wants or doesn't want to play again). I checked if the actual strcmp() in the int resultat (char* word, char* mask, int count) function worked, and it did. So the fault has be with the strings being compared. I think it's when I get the lenght of the chosen word with strlen(). When I get the length, I subtract with one because otherwise I would get a lenght which is too long(for example, paper would give a lenght of 6, but when I subtract with one I get 5).
If someone could help me or maybe give me some hints I would be very grateful!
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
#include<string.h>
#include<time.h>
#define MAX_WORD_LEN 20
char* datorns_val();
int ordlengd(char* word);
char* datorns_val_mask(char* word, int len);
int spel(char* word, char* mask, int len, int count, int result);
int resultat (char* word, char* mask, int count);
char get_user_choice();
void hangman(int count, int result);
const int MAX_GUESS = 6;
const char ABORT_CH = '0';
const int LOOSE = 0;
const int WIN = 1;
const int ABORTED = 2;
/************************************************************
*
* MAIN
*
*
************************************************************/
int main ()
{
char word[MAX_WORD_LEN];
char mask[MAX_WORD_LEN];
int ch;
int len;
int result;
int count;
/* -------------------- Programstart -----------------*/
srand(time(NULL));
while (true)
{
result = 5;
count = 0;
strcpy(word,datorns_val());
printf("Valt ord 2: %s", word);
free(datorns_val());
len = ordlengd(word);
strcpy(mask,datorns_val_mask(word,len));
printf("\nMask 2: %s <-----", mask);
free(datorns_val_mask(word,len));
printf( "\nV\x84lkommen till HANGMAN 2014!\n");
printf( "Du har %d gissningar p\x86 dig (avbryt med 0)\n", MAX_GUESS );
printf( "Datorn har nu valt ett ord p\x86 %d bokst\x84ver\n", len );
/* GAME MAIN LOOP */
while (count < 6)
{
count=spel(word,mask,len,count,result);
result=resultat(word,mask,count);
hangman(count,result);
}
/* END MAIN GAME LOOP */
if( result == WIN )
{
printf("\nGrattis du vann!\n");
}
else if( result == LOOSE )
{
printf("\nTyv\x84rr du f\x94rlorade! Ordet var: %s\n", word);
}
else
{
printf("Avbrutet\n");
}
printf("Vill du spela igen? (j/n)");
ch = get_user_choice();
if (ch == 'n' || ch == 'N')
{
break;
}
}
}
/***********************************************************
*
* --------- Funktionsdefinitioner ----------------
*
***********************************************************/
char get_user_choice()
{
char tkn;
scanf(" %c", &tkn);
return tkn;
}
char* datorns_val()
{
char ordlista[20];
char* valt_ord = malloc(20);
int random;
int raknare = 0;
random = rand()%4+1;
FILE *ptr_file;
ptr_file =fopen("hangman.dat","r");
if (!ptr_file)
{
printf("Filen kunde inte öppnas!");
}
while (fgets(ordlista,20, ptr_file)!= NULL)
{
if (raknare == random)
{
strcpy(valt_ord, ordlista);
break;
}
raknare=raknare+1;
}
printf("Valt ord 1: %s",valt_ord);
fclose(ptr_file);
return valt_ord;
}
int ordlengd(char* word)
{
printf("Valt ord 3: %s", word);
int ordlengd;
ordlengd=strlen(word)-1;
printf("Ordlengd 1: %i", ordlengd);
return ordlengd;
}
char* datorns_val_mask(char* word, int len)
{
int j;
char* gissning = malloc(20);
for (j=0; j<len; j++)
{
gissning[j]='_';
}
printf("\nMask 1: %s <----", gissning);
return gissning;
}
int spel(char* word, char* mask, int len, int count, int result)
{
int j;
char bokstav;
int ratt = 0;
printf("\nSkriv en bokstav: ");
scanf(" %c", &bokstav);
for(j=0; j<len; j++)
{
if(bokstav==word[j])
{
mask[j]=bokstav;
ratt = 1;
}
else if(bokstav=='0')
{
count = 7;
return count;
}
}
if (ratt == 0)
{
printf("\nBokstaven finns inte i ordet!\n");
count=count+1;
}
printf("Antal fel: %i\n\n", count);
ratt = 0;
for (j=0; j<len; j++)
{
printf("%c", mask[j]);
printf(" ");
}
return count;
}
void hangman(int count, int result)
{
const char* str[20];
int j;
str[0]="\n_______ \n";
str[1]=" | \n";
str[2]=" O \n";
str[3]="//|\\\\\n";
str[4]=" | \n";
str[5]="// \\\\\n";
if(result != ABORTED)
{
for (j=0; j<count; j++)
{
printf("%s", str[j]);
}
}
}
int resultat (char* word, char* mask, int count)
{
char* a = "Hej";
char* b = "Hej";
if (count == 6)
{
return LOOSE;
}
else if (count < 6 && strcmp(mask,word) == 0)
{
return WIN;
}
else if (count == 7)
{
return ABORTED;
}
}
There are some things around the code:
1) The first free() call in pointless:
free(datorns_val());
This reserves memory for a string and deletes it without making any use of it. So get rid of it.
2) Using fgets() to read strings from a file stores also the '\n' character at the end of the line into your string, so you must get rid of it. As a hint, I have used this sentence:
while(fscanf(ptr_file,"%s", ordlista) >0)
that does not store '\n' characters.
3) In ordlengd(char* word) function, you had problem with an extra character (the above mentioned '\n') so the length is the same as the one returned by strlen(), not the
strlen(word) - 1
you had written.
4) You have think about another condition to end the while loop of the main function. I would suggest to add
else return 5;
at the end of resultat() function and the check this value en the while loop of the main function
while (count < 6 && result == 5)
Hope it helps
Consider the following simple C program.
//C test
#include<stdio.h>
int main()
{
int a, b, c;
printf("Enter two numbers to add\n");
scanf("%d%d",&a,&b);
c = a + b;
printf("Sum of entered numbers = %d\n",c);
return 0;
}
How do you check the values entered are actually two integers in some sensible range? Currently, if you just enter "a" and then return you get the output "Sum of entered numbers = 32767".
Examples of incorrect input I would like to prevent.
2 3 4 (wrong number of numbers)
apple (not a number)
11111111111111111111111111 1111111111111111111111111111111111111 (numbers out of range)
Or should I be using fgets and sscanf or even strtol ?
User input is evil. Parse per:
(optional whitespace)[decimal int][whitespace][decimal int](optional whitespace)
strtol() and family have better error handling than scanf().
Coda: Best to handle user input in a helper function. Break into 2 parts: I/O and parsing.
#include <ctype.h>
#include <errno.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
// return 1 (success), -1 (EOF/IOError) or 0 (conversion failure)
int Readint(const char *prompt, int *dest, size_t n) {
char buf[n * 21 * 2]; // big enough for `n` 64-bit int and then 2x
fputs(prompt, stdout); // do not use printf here to avoid UB
fflush(stdout); // per #OP suggestion
if (fgets(buf, sizeof buf, stdin) == NULL) {
return -1;
}
const char *p = buf;
while (n-- > 0) {
char *endptr;
errno = 0;
long l = strtol(p, &endptr, 10);
if (errno || (p == endptr) || (l < INT_MIN) || (l > INT_MAX)) {
return 0;
}
*dest++ = (int) l;
p = endptr;
}
// Trailing whitespace OK
while (isspace((unsigned char) *p)) p++;
// Still more text
if (*p) return 0;
return 1;
}
int main() { // for testing
int Result;
do {
int dest[2] = { -1 };
Result = Readint("Enter two numbers to add\n", dest, 2);
printf("%d %d %d\n", Result, dest[0], dest[1]);
} while (Result >= 0);
return 0;
}
You can use like:
if( scanf("%d%d",&a,&b) == 2)
{
//two integer values has been read successfully
//do your stuff here
}
else
{
//Wrong input
}
Also you can do this to prevent anything after second number
int a,b;
char c;
if( scanf("%d%d%c", &a, &b, &c) == 3) {
if (c == '\n') {
puts("good");
}
} else {
puts("bad");
}
return 0;
}
You can use the following macro
#define SCAN_ONEENTRY_WITHCHECK(FORM,X,COND) \
do {\
char tmp;\
while(((scanf(" "FORM"%c",X,&tmp)!=2 || !isspace(tmp)) && !scanf("%*[^\n]"))\
|| !(COND)) {\
printf("Invalid input, please enter again: ");\
}\
} while(0)
and you call it in this way in the main
int main()
{
int a, b, c;
printf("Input first integer, valid choice between 0 and 10: ");
SCAN_ONEENTRY_WITHCHECK("%d",&a,(a>=0 && a<=10));
printf("Input second integer, valid choice between 0 and 10: ");
SCAN_ONEENTRY_WITHCHECK("%d",&b,(b>=0 && b<=10));
c = a + b;
printf("Sum of entered numbers = %d\n",c);
return 0;
}
for more detail concerning this macro please refer to: Common macro to read input data and check its validity
A simple way would be,
int a=0, b=0, c=0;
initialise them to 0
Additionally, the check suggested by Midhun is good to check if there are two inputs.
you can test this one.
#include <stdio.h>
int main(void)
{
int a, b, c;
printf("Enter two numbers to add\n");
scanf("%d%d",&a,&b);
if(scanf("%d%d",&a,&b) == 2)
{
c = a + b;
printf("Sum of entered numbers = %d\n",c);
}
return 0;
}
I am coding in C on linux, and I need to reverse a number. (EG: 12345 would turn into 54321), I was going to just convert it into a string using itoa and then reverse that, as it's probably a lot easier with string manipulation, however it turns out itoa is non standard and isn't included in gcc. Is there a way of doing a binary rotation style thing on decimal numbers and if not what approach should I take?
int n;
scanf("%d",&n);
int rev=0,rem;
while(n>0)
{
rem=n%10; //take out the remainder .. so it becomes 5 for 12345
rev=rev*10+rem; //multiply the current number by 10 and add this remainder.
n=n/10; //divide the number. So it becomes 1234.
}
printf("%d",rev);
#include<stdio.h>
main()
{
int rev=0,n;
scanf("%d",&n);
while(n)
{
rev=10*rev+n%10;
n/=10;
}
printf("result=%d",rev);
}
Do it without strings.
fkt()
{
int i = 12345;
int n = 0;
int x;
char nr[10];
char *p = &nr[0];
while(i != 0)
{
x = i % 10;
i = i/10;
n = n * 10 + x;
*p = x+'0';
p++;
}
*p = 0;
printf("%d %s\n", n, nr);
return 0;
}
If you really want to use strings, you can use sprintf to do what itoa does.
int k = 12345;
char str[40];
sprintf(str,"%d",k);
Then reverse the string and convert it back to int using atoi or sscanf.
you can use stack to do this,
struct node
{
char character;
struct node *next;
};
struct node *list_head,*neos;
main()
{
list_head=NULL;
char str[14];
int number,i;
scanf("%d",&number);
sprintf(str,"%d",number); //here i convert number to string
for(i=0;i<strlen(str);i++) //until the end of the string
{
add_to_stack(str[i]); //i take every character and put it in the stack
}
print_the_number();
}
attention here,in stack the item
which is added last,
it taken out first,
that why it works..
void add_to_stack(char charac)
{
neos=(struct node*)malloc(sizeof(struct node));
neos->character=charac;
neos->next=list_head;
list_head=neos;
}
void print_the_number()
{
struct node *ptr;
ptr=list_head;
while(ptr!=NULL)
{
printf("%c",ptr->character);
ptr=ptr->next;
}
}
iota() is not a standard C function, but snprintf() serves the purpose just as well.
/* assume decimal conversion */
const char * my_itoa (int input, char *buffer, size_t buffersz) {
if (snprintf(buffer, sz, "%d", input) < sz) return buffer;
return 0;
}
Since the input cannot be negative, you can use an unsigned type:
unsigned long long irev (unsigned input) {
unsigned long long output = 0;
while (input) {
output = 10 * output + input % 10;
input /= 10;
}
return output;
}
Reversing the input may result in a value that no longer fits the input type, so the return result attempts to use a wider type. This may still fail if unsigned and unsigned long long have the same width. For such cases, it is probably easiest to use a string to represent the reversed value. Or, if the only goal is to print the number, you can just use a loop to print the digits in reverse order.
void print_irev (unsigned input) {
if (input) {
do {
putchar('0' + input % 10);
input /= 10;
} while (input);
} else {
putchar('0');
}
putchar('\n');
}
#include<iostream>
using namespace std;
int main()
{
int dig,n,rev=0;`
cout<<"enter number";
cin>>n;
while(n!=0)
{
dig=n%10;
rev=rev*10+dig;
n=n/10; }
if(n==0){
cout<<"palindrome of zeros ";
}
if(rev==1)
{
cout<<"reverse of 10 is 01";
}
//since exception occurs when user inputs 10 or 0s
else
{
cout<<"reverse of the number is ";
cout<<rev;
}
getch();
}
their are two methods
method 1 :
int n;
cin>>n;
int rev=0,rem;
while(n>0)
{
rem=n%10;
rev=rev*10+rem;
n=n/10;
}
cout<<rev;
method 2:
cin>>n; // size of array
int a[n+1]={0};
for(i=1;i<=n;i++)
cin>>a[i];
for(i=n;i>0;i--)
cout<<a[i];