I'm working on an assignment and as part of it I need to extract the integer from a string.
I've tried using the atoi() function, but it always returns a 0, so then I switched up to strtol(), but it still returns a 0.
The goal is to extract the integers from the string and pass them as arguments to a different function. I'm using a function that then uses these values to update some data (update_stats).
Please keep in mind that I'm fairly new to programming in the C language, but this was my attempt:
void get_number (char str[]) {
char *end;
int num;
num = strtol(str, &end, 10);
update_stats(num);
num = strtol(end, &end, 10);
update_stats(num);
}
The purpose of this is in a string "e5 d8" (for example) I would extract the 5 and the 8 from that string.
The format of the string is always the same.
How can I do this?
strtol doesn't find a number in a string. It converts the number at the beginning of the string. (It does skip whitespace, but nothing else.)
If you need to find where a number starts, you can use something like:
const char* nump = strpbrk(str, "0123456789");
if (nump == NULL) /* No number, handle error*/
(man strpbrk)
If your numbers might be signed, you'll need something a bit more sophisticated. One way is to do the above and then back up one character if the previous character is -. But watch out for the beginning of the string:
if ( nump != str && nump[-1] == '-') --nump;
Just putting - into the strpbrk argument would produce false matches on input like non-numeric7.
If the format is always like this, then this could also work
#include <stdio.h>
int main()
{
char *str[] = {"a5 d8", "fe55 eec2", "a5 abc111"};
int num1, num2;
for (int i = 0; i < 3; i++) {
sscanf(str[i], "%*[^0-9]%d%*[^0-9]%d", &num1, &num2);
printf("num1: %d, num2: %d\n", num1, num2);
}
return 0;
}
Output
num1: 5, num2: 8
num1: 55, num2: 2
num1: 5, num2: 111
%[^0-9] will match any non digit character. By adding the * like this %*[^0-9] indicates that the data is to be read from the string, but ignored.
I suggest you write the logic on your own. I know, it's like reinventing the wheel, but in that case, you will have an insight into how the library functions actually work.
Here is a function I propose:
bool getNumber(str,num_ptr)
char* str;
long* num_ptr;
{
bool flag = false;
int i = 0;
*num_ptr = 0;
char ch = ' ';
while (ch != '\0') {
ch = *(str + i);
if (ch >= '0' && ch <= '9') {
*num_ptr = (*num_ptr) * 10 + (long)(ch - 48);
flag = true;
}
i++;
}
return flag;
}
Don't forget to pass a string with a \0 at the end :)
Related
(i'm french, sorry for my bad english)
I don't know how to get an int from a char[], the patern of the char will be the same everytime : "prendre 2", "prendre 44", "prendre 710"...
I want to check if the pattern of the sentence is correct and get the integer.
I have try to do this, but as you see, the problem is i just can check if the integer is between 0-9 because I check only one char.
[...]
else if (est_prendre(commande)){
/* if the output is 1*/
int number = commande[8]- '0'
}
int est_prendre(char *commande){
int i;
char temp[9] = "";
char c = commande[8];
int num = c - '0';
for (i=0; i<8; i++){
temp[i] = commande[i];
}
if (strcmp ("prendre ", temp) == 0)
{
if ( /* num IS INTEGER? */)
{
return 1;
}
else
{
return 0;
}
} else {
return 0;
}
}
I expect if commande = "prendre 3", output of est_prendre is 1 because the pattern is correct
And after than to put the integer into the variable number.
Thank You!
Assuming that 'commande + 8' is a valid substring, what you need is atoi() function (ASCII to Integer). This function is widely documented, and you can easily find online its usage.
int number = atoi(commande+8);
Just remember that the substring terminates at the first non-digit character:
atoi("23") returns 23
atoi("51hh37") returns 51
atoi("z3456") returns 0
Note: atoi converts input string into integer, and you can use it if you are sure it fits expected input. So, if you expect to have either long integers or float values in your string you can use atol() (ASCII to long) or atof() (ASCII to float).
This is very basic, you should (re)read any reference/tutorial on C that you have used to learn the language.
You should just use the sscanf() standard function:
int value;
if (sscanf(commande, "prendre %d", &value) == 1)
{
... it was a match, the variable 'value' will be set to the number from the string
}
you can delete the (strange-looking) code that copies characters from commande to temp, and the temp variable too of course. Just inspect the commande string directly.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 7 years ago.
Improve this question
I have to write a program that converts an user input (which is a string) to an Integer. In the same time it should check, if the user input really is a number.
And also everything in one method.
and NO LIBRARY FUNCTIONS allowed.
I can't figure any idea how to do it. All I got for the beginning is just this pathetic structure
#include <stdio.h>
void main()
{
char input[100];
int i;
int sum = 0;
printf("Type a String which will be converted to an Integer: ");
scanf("%c, &input");
for (i = 0; i < 100; i++)
{
}
}
I appreciate any help, thanks
The conversion is the easy part...
But if you must not use library functions,
there is only one way to take a string, and that is argv;
there is only one way to give an integer, and that is the exit code of the program.
So, without much ado:
int main( int argc, char * argv[] )
{
int rc = 0;
if ( argc == 2 ) // one, and only one parameter given
{
unsigned i = 0;
// C guarantees that '0'-'9' have consecutive values
while ( argv[1][i] >= '0' && argv[1][i] <= '9' )
{
rc *= 10;
rc += argv[1][i] - '0';
++i;
}
}
return rc;
}
I did not implement checking for '+' or '-', and did not come up with a way to signal "input is not a number". I also just stop parsing at the first non-digit. All this could probably be improved upon, but this should give you an idea of how to work around the "no library functions" restriction.
(Since this sounds like a homework, you should have to write some code of your own. I already gave you three big spoons of helping regarding argv, the '0'-'9', and the conversion itself.)
Call as:
<program name> <value>
(E.g. ./myprogram 28)
Check return code with (for Linux shell):
echo $?
On Windows it's something about echo %ERRORLEVEL% or somesuch... perhaps a helpful Windows user will drop a comment about this.
Source for the "'0'-'9' consecutive" claim: ISO/IEC 9899:1999 5.2.1 Character sets, paragraph 3:
In both the source and execution basic character sets, the value of each character after 0 in the above list of decimal digits shall be one greater than the value of the previous.
I'm sure this is preserved in C11, but I only have the older C99 paper available.
Take hightes digit and add it to number, multiply the number by 10 and add the next digit. And so on:
#include <stdio.h> // scanf, printf
void main()
{
char input[100];
printf("Type a String which will be converted to an Integer: ");
scanf("%s", input);
int number = 0;
int neg = input[0] == '-';
int i = neg ? 1 : 0;
while ( input[i] >= '0' && input[i] <= '9' )
{
number *= 10; // multiply number by 10
number += input[i] - '0'; // convet ASCII '0'..'9' to digit 0..9 and add it to number
i ++; // step one digit forward
}
if ( neg )
number *= -1;
printf( "string %s -> number %d", input, number );
}
input[i] - '0' works, because ASCII characters '0'..'9' have ascending ASCII codes from 48 to 57.
So basically you want to know how something like the standard library atoi works. In order to do this, you need to consider how strings represent numbers.
Basically, a string (that represents a number) is a list o digits from 0 to 9. The string abcd (where a, b, c, d are placeholders for any digit) represents the number a*10 ^ 3 + b*10^2 + c * 10 + d (considering base 10 here, similar for other bases). So basically you need to decompose the string as shown above and perform the required arhitmetic operations:
// s - the string to convert
int result = 0;
for (int index = 0; index < strlen(s); index++) {
result = result * 10 + s[index] - '0';
}
The operation s[index] - '0' converts the character that represent a digit to its value.
// the function returns true for success , and false for failure
// the result is stored in result parameter
// nb: overflow not handled
int charToInt(char *buff,int *result){
*result=0;
char c;
while(c=*buff++){
if((c < '0') || (c >'9')) // accept only digits;
return 0;
*result *= 10;
*result += c-'0';
}
return 1;
}
Lot of things which are missed. Firstly taking a string in is done by scanf("%s",input); By the way in which you are receiving it, it only stores a character, secondly run the loop till the length of the string recieved. Check the below code.
#include <stdio.h>
#include<string.h>
void main()
{
char input[100];
int i;
int sum = 0;
printf("Type a String which will be converted to an Integer: ");
scanf("%s", input);
for (i = 0; i < strlen(input); i++)
{
if(input[i]>=48 && input[i]<=57)
{
//do something, it is a digit
printf("%d",input[i]-48);
//48 is ascii value of 0
}
}
Try it:
#include <stdio.h>
void main()
{
char input[100];
int i,j;
int val = 0;
printf("Type a String which will be converted to an Integer: ");
scanf("%s",input);
for(j=0; input[j] != '\0'; j++); // find string size
for (i = 0; i < j; i++)
{
val = val * 10 + input[i] - 48;
}
}
If you want your code to be portable to systems that don't use ASCII, you'll have to loop over your char array and compare each individual character in the source against each possible number character, like so:
int digit;
switch(arr[i]) {
case '0':
digit=0; break;
case '1':
digit=1; break;
// etc
default:
// error handling
}
Then, add the digit to your result variable (after multiplying it by 10).
If you can assume ASCII, you can replace the whole switch statement by this:
if(isdigit(arr[i])) {
digit=arr[i] - '0';
} else {
// error handling
}
This works because in the ASCII table, all digits are found in a single range, in ascending order. By subtracting the ordinal value of the zero character, you get the value of that digit. By adding the isdigit() macro, you additionally ensure that only digit characters are converted in this manner.
I need to call a c-function from matlab using y=coder.ceval() and return a string from the function. However the coder.ceval() function only allows me to return a scalar value. String is however an array of char, and thus cannot be returned. The code in matlab function looks like:
function y = abc(param)
y = '';
if strcmp(coder.target,'rtw'),
y=coder.ceval('c-function',param);
end
end
Is there any solution or workaround for it?
Looking forward for some help. Thank you very much!
EDITING
This is a workaround and you should use it at your own risk! ;)
I mean if it is really your last option.
As you do not specify the kind of string I assume for simplicity that it is composed only by uppercase letters (AABBBCC).
Uppercase letters are represented as decimal numbers by 2 digits (A = 65, Z = 90, man ascii).
This method comprises two steps:
1) In your function that you call via coder.ceval you should build a scalar value from the string you want to return. 2) You have to rebuild the string from the scalar value.
The following code illustrates by a simple example how to carry out the two steps. Keep in mind that is only an example and you have to work on it. Let's suppose for example that you need to return the string "ABC" then you can return the scalar "656667" which is composed by the three 2-digits numbers: 65=A, 66=B, 67=C.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
int i, len, n;
// First convert a string in a scalar value
char str[] = {'A', 'B', 'C', '\0'};
printf("str = %s\n", str);
len = strlen(str);
for (i = 0; i < len; i++) {
n = str[i] + i*100;
}
printf("n = %d\n", n);
// You return a scalar that is composed by 65,66,67 ---> A,B,C
int y = 656667;
char num[100];
char letter[3];
// convert the number in a string
snprintf(num, 100, "%d", y);
printf("num = %s\n", num);
len = strlen(num);
printf("num len = %d\n", len);
// here we assume that the number of digits id even only ascii letters
if ((len%2) != 0) exit(1);
// Now we have to store the number of two digits as numbers and
// then convert the to char and finally append tehm to a string
int *ni = malloc((len/2)*sizeof(int));
char *string = malloc(len + 1);
// Here I use a lot of intermediate steps to make it clear
char c = 0;
for (i = 0; i < len/2; i+=1) {
snprintf(letter, 3, "%c%c", num[2*i], num[2*i+1]);
ni[i] = atoi(letter);
c = (char)ni[i];
printf("letter %d = %s, x = %d, c = %c\n", i, letter, ni[i], c);
string[i] = c;
printf("string[%d] = %c\n", i, string[i]);
}
// print the final string
string[len] = '\0';
printf("string = %s\n", string);
return 0;
}
Lowercase letters starts at 97 but then become 3 digits, however by using some "special number" of 2 digits one can even decide to read 2 digits at the beginning of the string and 3 digits after the "special number".
Ok, I am not sure that this will help but, at least, I hope you find it interesting.
I'm trying to take all of the numbers out of a string (char*)...
Here's what I have right now:
// Take numbers out of username if they exist - don't care about these
char * newStr;
strtoul(user, &newStr, 10);
user = newStr;
My understanding is that strtoul is supposed to convert a string to an unsigned long. The characters that are not numbers are put into the passed in pointer (the 2nd arg). When i reassign user to newStr and print it, the string remains unchanged. Why is this? Does anyone know of a better method?
From the documentation example:
#include <stdio.h>
#include <stdlib.h>
int main()
{
char str[30] = "2030300 This is test";
char *ptr;
long ret;
ret = strtoul(str, &ptr, 10);
printf("The number(unsigned long integer) is %lu\n", ret);
printf("String part is |%s|", ptr);
return(0);
}
Let us compile and run the above program, this will produce the following result:
The number(unsigned long integer) is 2030300
String part is | This is test|
char* RemoveDigits(char* input)
{
char* dest = input;
char* src = input;
while(*src)
{
if (isdigit(*src)) { src++; continue; }
*dest++ = *src++;
}
*dest = '\0';
return input;
}
Test:
int main(void)
{
char inText[] = "123 Mickey 456";
printf("The result is %s\n", RemoveDigits(inText));
// Expected Output: " Mickey "
}
The numbers were removed.
Here is a C program to remove digits from a string without using inbuilt functions. The string is shifted left to overwrite the digits:
#include <stdio.h>
int main(void) {
char a[] = "stack123overflow";
int i, j;
for (i = 0; a[i] != '\0'; i ++) {
if (a[i] == '0' || a[i] == '1' || a[i] == '2' || a[i] == '3' || a[i] == '4' || a[i] == '5' || a[i] == '6' || a[i] == '7' || a[i] == '8' || a[i] == '9') {
for (j = i; a[j] != '\0'; j ++)
a[j] = a[j + 1];
i--;
}
}
printf("%s", a);
return 0;
}
Example of execution:
$ gcc shift_str.c -o shift_str
$ ./shift_str
stackoverflow
strtoul() does not extract all numbers from string, it just trying to covert string to number and convertion stops when non digit is find. So if your string starts from number strtoul() works as you expect, but if string starts from letters, strtoul() stops at the first symbol. To solve your task in simple way you should copy all non-digits to other string, that will be a result.
The problem you are having is that strtoul is converting characters at the beginning of the string into an unsigned long. Once it encounters non-numeric digits, it stops.
The second parameter is a pointer into the original character buffer, pointing at the first non-numeric character.
http://www.cplusplus.com/reference/cstdlib/strtoul/
Parameter 2 : Reference to an object of type char*, whose value is set by the function to the next character in str after the numerical value.
So, if you tried to run the function on "123abc567efg" the returned value would be 123. The original string buffer would still be "123abc567efg" with the second parameter now pointing at the character 'a' in that buffer. That is, the pointer (ptr) will have a value 3 greater than original buffer pointer (str). Printing the string ptr, would give you "abc567efg" as it simply points back into the original buffer.
To actually remove ALL the digits from the string in C you would need to do something similar to this answer : Removing spaces and special characters from string
You build your allowable function to return false on 0-9 and true otherwise. Loop through and copy out digits to a new buffer.
I want to convert a char array[] like:
char myarray[4] = {'-','1','2','3'}; //where the - means it is negative
So it should be the integer: -1234
using standard libaries in C. I could not find any elegant way to do that.
I can append the '\0' for sure.
I personally don't like atoi function. I would suggest sscanf:
char myarray[5] = {'-', '1', '2', '3', '\0'};
int i;
sscanf(myarray, "%d", &i);
It's very standard, it's in the stdio.h library :)
And in my opinion, it allows you much more freedom than atoi, arbitrary formatting of your number-string, and probably also allows for non-number characters at the end.
EDIT
I just found this wonderful question here on the site that explains and compares 3 different ways to do it - atoi, sscanf and strtol. Also, there is a nice more-detailed insight into sscanf (actually, the whole family of *scanf functions).
EDIT2
Looks like it's not just me personally disliking the atoi function. Here's a link to an answer explaining that the atoi function is deprecated and should not be used in newer code.
Why not just use atoi? For example:
char myarray[4] = {'-','1','2','3'};
int i = atoi(myarray);
printf("%d\n", i);
Gives me, as expected:
-123
Update: why not - the character array is not null terminated. Doh!
It isn't that hard to deal with the character array itself without converting the array to a string. Especially in the case where the length of the character array is know or can be easily found. With the character array, the length must be determined in the same scope as the array definition, e.g.:
size_t len sizeof myarray/sizeof *myarray;
For strings you, of course, have strlen available.
With the length known, regardless of whether it is a character array or a string, you can convert the character values to a number with a short function similar to the following:
/* convert character array to integer */
int char2int (char *array, size_t n)
{
int number = 0;
int mult = 1;
n = (int)n < 0 ? -n : n; /* quick absolute value check */
/* for each character in array */
while (n--)
{
/* if not digit or '-', check if number > 0, break or continue */
if ((array[n] < '0' || array[n] > '9') && array[n] != '-') {
if (number)
break;
else
continue;
}
if (array[n] == '-') { /* if '-' if number, negate, break */
if (number) {
number = -number;
break;
}
}
else { /* convert digit to numeric value */
number += (array[n] - '0') * mult;
mult *= 10;
}
}
return number;
}
Above is simply the standard char to int conversion approach with a few additional conditionals included. To handle stray characters, in addition to the digits and '-', the only trick is making smart choices about when to start collecting digits and when to stop.
If you start collecting digits for conversion when you encounter the first digit, then the conversion ends when you encounter the first '-' or non-digit. This makes the conversion much more convenient when interested in indexes such as (e.g. file_0127.txt).
A short example of its use:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int char2int (char *array, size_t n);
int main (void) {
char myarray[4] = {'-','1','2','3'};
char *string = "some-goofy-string-with-123-inside";
char *fname = "file-0123.txt";
size_t mlen = sizeof myarray/sizeof *myarray;
size_t slen = strlen (string);
size_t flen = strlen (fname);
printf ("\n myarray[4] = {'-','1','2','3'};\n\n");
printf (" char2int (myarray, mlen): %d\n\n", char2int (myarray, mlen));
printf (" string = \"some-goofy-string-with-123-inside\";\n\n");
printf (" char2int (string, slen) : %d\n\n", char2int (string, slen));
printf (" fname = \"file-0123.txt\";\n\n");
printf (" char2int (fname, flen) : %d\n\n", char2int (fname, flen));
return 0;
}
Note: when faced with '-' delimited file indexes (or the like), it is up to you to negate the result. (e.g. file-0123.txt compared to file_0123.txt where the first would return -123 while the second 123).
Example Output
$ ./bin/atoic_array
myarray[4] = {'-','1','2','3'};
char2int (myarray, mlen): -123
string = "some-goofy-string-with-123-inside";
char2int (string, slen) : -123
fname = "file-0123.txt";
char2int (fname, flen) : -123
Note: there are always corner cases, etc. that can cause problems. This isn't intended to be 100% bulletproof in all character sets, etc., but instead work an overwhelming majority of the time and provide additional conversion flexibility without the initial parsing or conversion to string required by atoi or strtol, etc.
So, the idea is to convert character numbers (in single quotes, e.g. '8') to integer expression. For instance char c = '8'; int i = c - '0' //would yield integer 8; And sum up all the converted numbers by the principle that 908=9*100+0*10+8, which is done in a loop.
char t[5] = {'-', '9', '0', '8', '\0'}; //Should be terminated properly.
int s = 1;
int i = -1;
int res = 0;
if (c[0] == '-') {
s = -1;
i = 0;
}
while (c[++i] != '\0') { //iterate until the array end
res = res*10 + (c[i] - '0'); //generating the integer according to read parsed numbers.
}
res = res*s; //answer: -908
It's not what the question asks but I used #Rich Drummond 's answer for a char array read in from stdin which is null terminated.
char *buff;
size_t buff_size = 100;
int choice;
do{
buff = (char *)malloc(buff_size *sizeof(char));
getline(&buff, &buff_size, stdin);
choice = atoi(buff);
free(buff);
}while((choice<1)&&(choice>9));