string to integer - c

I have made a program which converts numbers entered into a string into an integer like atoi does, but its giving wrong output.
#include<stdio.h>
#include<conio.h>
#include<math.h>
#include<string.h>
void main(void)
{
static int sum;
int i,x,y,z;
char string[10];
printf("Enter a string:\n");
gets(string);
x=strlen(string);
for(i=0; ;i++)
{
if(string[i]=='\0')
{
break;
}
y=pow(10,i);
z=string[x-i+1]*y;
sum+=z;
}
printf("%d",sum);
getch();
}

Ok. Here is a quick review of your code. Comments embedded.
#include<stdio.h>
Leave a space between #include and <stdio.h>.
#include<conio.h>
This is a non-standard Windows-only header that you don't need. Don't include this.
#include<math.h>
#include<string.h>
Again use a space, when including your headers.
void main(void)
While this is legal, it is more common to find the signature int main(int argc, char* argv[]) as the signature for the main function. I would suggest that you use that signature.
{
static int sum;
Why are you making this static? Are you planning to invoke main repeatedly and have the previous result for sum persist from one invocation of main to another? If not, then don't make it static.
int i,x,y,z;
char string[10];
Consider allocating more space for your string. Ten characters is quite small. Also consider creating a variable to represent the size of your string, rather than using a magic number, since you will likely have to reference the buffer size in multiple places.
printf("Enter a string:\n");
gets(string);
No. Don't do that!!! The function gets is a major security vulnerability!. It makes your program susceptible to buffer overflow attacks. Instead, use fgets, and specify the size of the buffer that you want to fill, so that it doesn't overrun your buffer. You should never, ever use plain gets.
x=strlen(string);
Consider choosing a more descriptive name for x. Perhaps len. It is perfectly ok (and good) to create variables that have identifiers longer than a single letter.
for(i=0; ;i++)
{
if(string[i]=='\0')
{
break;
}
Consider putting the termination condition in the for-loop; for(i = 0; string[i]!='\0'; i++).
y=pow(10,i);
z=string[x-i+1]*y;
Hint: there is a smarter way to do this than using pow.
sum+=z;
}
printf("%d",sum);
Ok. The above is fine, although you might want to use "%d\n".
getch();
You really shouldn't be doing this on all systems. Instead, do:
#ifdef _WIN32
system("pause");
#endif
If possible, though, I would suggest you avoid that weird pausing behavior. Suppose your professor uses an automated script to validate the output of your program. Putting any sort of pause in the program (even on Windows), will break such a script. If you don't want the terminal window to disappear while on Windows, you should invoke your program from the command prompt.
}
If you were to change the signature to something returning int as I suggested, then you would want to add the statement return 0; before the end of the function.

Your string do not contain the int values 0, 1, 2, ... 9.
They contain the char values '0', '1', '2', ... '9'. Encoded in e.g. ASCII, '0' == 48.
You need to convert the char to int; one way to do this is by subtracting '0', e.g.:
z = (string[x-i+1] - '0') * y;
Related questions
Please explain what this code is doing (someChar - 48)
How to convert a single char into an int
Language showdown: Convert string of digits to array of integers?
Many examples of digit conversion, using subtraction with both '0' and 48!
On Horner's Scheme
You can also do better by not using the pow, by using Horner scheme.
Here's an example (here ^ denotes exponentiation instead of bitwise-xor):
8675309 = 8*10^6 + 6*10^5 + 7*10^4 + 5*10^3 + 3*10^2 + 0*10^1 + 9*10^0
= (((((8*10 + 6)*10 + 7)*10 + 5)*10 + 3)*10 + 0)*10 + 9
It may look complicated at first, but it really isn't. You basically read the digits left to right, and you multiply your result so far by 10 before adding the next digit.
In table form:
step result digit result*10+digit
1 init=0 8 8
2 8 6 86
3 86 7 867
4 867 5 8675
5 8675 3 86753
6 86753 0 867530
7 867530 9 8675309=final
I'll leave you to implement this simple algorithm on your own, since this is homework.
See also
Wikipedia/Horner Scheme
Related questions
What does the ^ operator do in Java?

it should be:
z=(string[x-(i+1)]-'0')*y;

Related

C11: how to quickly convert a char array into ints, then modify ints and update char array

There are two parts of the problem that I don't know how to solve:
Input
The user can enter some inputs like 12,14y or 15m and I need to extract the two ints and the character. For now, I simply use:
char buffer[50];
scanf("%s", buffer);
switch (buffer[strlen(buffer)-1]) {
// ... I use this to read the last char
}
This can give me the information of how many ints I have to read:
one in the m,n case -> sscanf(buffer, "%d%c", int1, c)
two in the y,s,b case -> sscanf(buffer, "%d,%d%c", int1, int2, c)
I need these numbers for the core of my program, so I need int values not only the string.
The problem is that online I read about sscanf inefficiency and I need a good way to do this task quickly.
Output
My code has to modify these numbers just in one case (y) and conserve a modified copy of the user input. For example, users input is 1,12y then I have to modify it in 1,10y and store it as a char array so it's not only an input. The modification of int2 it's quite long to explain, I can say that the new value would be less than the original one (in my example from 12 I get 10). The only idea I have about this it's how to create the new char array: I can calculate int1 and int2 length trying to divide them with increasing power of 10 until I get a result between 1 and 9. e.g.:
int1 = 201:
201 no
20.1 no
2.01 yes
=> 3 tries, length = 3
Then I use a malloc. But then, how can I write my "output" in the new char array? e.g.:
input = "1,201y"
-> int1 = 1, int2 = 201
-> lenght(int1) = 1, length(int2) = 2
// if the core program sets int2 = 51, then
char *out = malloc(1+2+1):
// now I have to write "1,51y" in this char array
I've coded the "core" program already, but now I'd want to improve a fast "translation" of user input (because in the core program I need to know if it's a int1m or int1n or int1,int2y or int1,int2s or int1,int2b command) and I don't know how to modify user input to save it in a string (for strings I use char arrays dynamically allocated). Only the y command could modify int2.
I hope that it's clear what I've to done.
The problem is that online I read about sscanf inefficiency
"Online" isn't a very trustworthy source. Inefficiency depends entirely on what you compare the function with.
If you compare with any plain C function then all of the stdio.h functions are very much inefficient. As is malloc for that matter. However, printing to the screen and waiting on the human user are by far the largest bottlenecks in this program, so you might want to re-consider why and what you are optimizing.
That being said, you can easily roll out a manual specialized version of the string to integer conversion, by calling strtol family of functions. Here's a version supporting exactly 1 or 2 integers in the input string (it can easily be rewritten to use a loop instead):
#include <stdlib.h>
int parse_input (const char* input, int* i1, int* i2, char* ch)
{
char* endptr=NULL;
const char* cptr=input;
int result;
result = strtol(cptr, &endptr, 10);
if(cptr==endptr)
{
return 0;
}
*i1 = result;
if(*endptr != ',')
{
*ch = *endptr;
return 1;
}
cptr=endptr+1;
result = strtol(cptr, &endptr, 10);
if(cptr==endptr)
{
return 0;
}
*i2 = result;
*ch = *endptr;
return 2;
}
Some extra error handling might be needed too. This gives around 50 instructions when compiled for x86_64, not counting strtol calls. Where some 20 of those instructions are related to the parameter stacking and calling convention.

How to add Strings from a Char Array to a String in C

I'm trying to create a program that generates random words from Katakana (Japanese syllables).
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <wchar.h>
#include <locale.h>
char* word;
char *kata[] = {"ア", "イ", "ウ", "エ", "オ", "カ", "キ", "ク", "ケ", "コ", "サ", "シ", "ス","セ","ソ","タ","チ","ツ","テ","ト","ナ","ニ","ヌ",
"ネ","ノ","ハ","ヒ","フ","ヘ","ホ","マ","ミ","ム","メ","モ","ヤ","ユ","ヨ","ラ","リ","ル","レ","ロ","ワ","ヲ","ン","ガ","ギ",
"グ","ゲ","ゴ","ザ","ジ","ズ","ゼ","ゾ","ダ","ヂ","ヅ","デ","ド","バ","ビ","ブ","ベ","ボ","パ","ピ","プ","ペ","ポ","ャ","ュ",
"ョ","ヴ","ァ","ィ","ゥ","ェ","ォ"};
int x = 0;
void generator (int length) {
for (int z=0; z<length; z++) {
x = rand() % sizeof(*kata);
concat(word,kata[x]);
}
}
int main (void) {
srand((unsigned) time(NULL));
int length = rand() % 5 + 2;
generator(length);
puts(word);
}
word is the String that I want to get printed, and kata is a Char Array containing Katakana. However, if I don't include the "*" to make the array an String array, C complains that there are multiple characters in a char. The rest of the code works fine in my testing.
I'm using BoUoW which has a full Ubuntu environment on Windows, so I don't think that's the problem, but rather how I'm putting the String array into the String.
I've done a similar program in Java in about an hour and this has taken me much longer. Although that's probably because I'm new to C.
Lot of check should be added (overflow on word for example)
The number of element on kata is the sizeof kata / sizeof an element you can do a macro countof
strcat is the function you need.
The idea is something like
char *kata[] = {"ア", "イ", "ウ", "エ", "オ", "カ", "キ", "ク", "ケ", "コ", "サ", "シ", "ス","セ","ソ","タ","チ","ツ","テ","ト","ナ","ニ","ヌ
",
"ネ","ノ","ハ","ヒ","フ","ヘ","ホ","マ","ミ","ム","メ","モ","ヤ","ユ","ヨ","ラ","リ","ル","レ","ロ","ワ","ヲ","ン","ガ","ギ",
"グ","ゲ","ゴ","ザ","ジ","ズ","ゼ","ゾ","ダ","ヂ","ヅ","デ","ド","バ","ビ","ブ","ベ","ボ","パ","ピ","プ","ペ","ポ","ャ","ュ",
"ョ","ヴ","ァ","ィ","ゥ","ェ","ォ"};
int x = 0;
static void generator (int nb, char *word, size_t n) {
word[0] = '\0';
while (nb-- > 0) {
x = rand() % (sizeof(kata) / sizeof(char*));
strcat(word, kata[x]);
}
}
int main (void) {
char word[64];
srand((unsigned) time(NULL));
int nb = rand() % 5 + 2;
generator(nb, word, sizeof(word));
puts(word);
return 0;
}
Which book are you reading? The reason I ask is that you've encountered a series of categorical errors regarding the fundamentals of C which people who read good books don't usually encounter. I can recommend K&R2E to someone who's already experienced programming from another language.
word is the String ...
Not in the code you've shown us, no... word contains a null pointer, and in your code you're assigning into that null pointer. Bad news :(
Stop confusing the concept of strings (which are a category of values) with pointers (which are a category of types).
A string is a sequence of character values that terminates at the first '\0'. That's a value. Strings are stored within arrays; an array is a category of type.
A pointer denotes a type which has values that point at/into arrays (which might or might not contain a string), functions or at nothing (which are null pointers).
... kata is a Char Array containing Katakana ...
Again, this isn't the case. kata is an array of char *. char * is not a character type; it's a character pointer type!
However, if I don't include the "*" to make the array an String array, C complains that there are multiple characters in a char.
I'm not sure what you expect. Since the type of a string literal expression such as "ア" is a char[n] (character array type) which gets converted to a char * (character pointer type) with a value pointing at the first character, and you store multiple of those in an array, the type of your array needs to be char *[m]. The * is necessary! I don't see a problem here.
I do see other problems, however. Firstly, concat isn't defined. You've not asked a question about this, so here's the definition I'll use to fill in the blanks:
void concat(char *dest, char *src) {
strcat(dest, src); // `strcat` is from `<string.h>`
}
sizeof(*kata) retrieves the size of a char *, which is commonly four or eight... so rand() % sizeof(*kata) will equate to rand() % 4 or rand % 8 on common systems. Perhaps you meant rand() % (sizeof kata / sizeof *kata). More on that later...
As I mentioned earlier, word is a null pointer and you can't assign into such a pointer. You need to make it point at something. You can do this by:
Using the &address-of operator on a variable. I assume this isn't suitable for you, as you'll want your pointer to point at a sequence of more than one object, but this is helpful to explain anyway. For example:
int x;
int *pointer_to_x = &x;
Declaring an array, and using the identifier of the array, possibly in conjunction with the + addition operator to point at an element in the array. For example:
int array[42];
int *pointer_to_first = array + 0;
int *pointer_to_second = array + 1;
Calling malloc, realloc, calloc or some other function that returns a pointer to a suitably sized object. For example:
int *pointer_to_whatever = malloc(42 * sizeof *pointer_to_whatever);
// Remember to free(pointer_to_whatever) ONCE when you're done with it
int isn't really appropriate for storing array indexes or lengths; you're better off using size_t as that doesn't have negative values which doesn't just eliminate some bugs, but also makes your code a little more efficient.
rand() % sizeof(*kata) isn't very random.
In fact, it's quite predictable. By reseeding with the same seed, another program can reproduce that exact sequence. By iterating on seeds, starting with seed = time(NULL) and moving backwards in time, it's easy enough to prove that this is no less predictable than a single int value, despite the fact that it is in fact multiple character values.
Additionally, rand tends to introduce biases, especially when you use the % operator to reduce it. You need to remove the bias. You could do this by first assigning your random number to a double, then dividing it by RAND_MAX + 1.0 like so:
double rand_double(void) {
return rand() / (RAND_MAX + 1.0);
}
With this function returning a value between 0.0 and 1.0 (excluding 1.0), you should be able to use rand_double() * (sizeof kata / sizeof *kata) for example, and this will be better... but the bias is still there; it's just reduced. To eliminate the bias, you need to consider that rand returns a sequence of values, each of which lie within [0..RAND_MAX], and that your range doesn't divide evenly into that range; the remainder of the division is a huge part of your bias. You need to take the range, and truncate it down to something that does divide evenly! That is, make a function that wraps rand and discards values greater than RAND_MAX - (RAND_MAX % (sizeof kata / sizeof *kata))... I've described (and solved) this problem in a solution I posted on gist, so for your convenience here's an adaptation of that code:
unsigned int rand_range(unsigned int ceiling) {
int n;
do {
n = rand();
} while (RAND_MAX - n <= RAND_MAX % ceiling);
return n % ceiling;
}
This is better again, but you won't want to use anything rand-derived for security purposes, so don't use this for passwords! This is because of the attack described earlier, where people can go back in time by reseeding to produce values previously generated. Use a cryptographically secure random number generator for that.

Program to convert a string to integer

The code I have written is as follows:
#include<stdio.h>
#include<math.h>
#include<string.h>
int strToint(char []);
int main()
{
char str[20];
printf("Enter the string-");
gets(str);
printf("\nthe integer is %d ",strToint(str));
return 0;
}
int strToint(char str[])
{
int i,a,sum=0,k,j;
a=strlen(str);
for(i=0;i<a;i++)
{
k=str[i]-'0';
j=pow(10,a-i-1);
sum+=k*j;
}
return sum;
}
If I enter the input as, say 567, I get 562 but I do not see why. I feel this is probably related to the pow function.
Help is appreciated. Thanks!
pow() is a floating point function and its behaviour varies from system to system. There's no requirement placed by the standard on its accuracy. It seems that yours is not returning values with the accuracy that you would require.
You do not need to implement functions to convert text to integer since the standard library contains functions that do that. An obvious choice would be sscanf.
But if you must implement such a function, you should use integer arithmetic. Any such code should handle negative values, and check for invalid input. For instance. What happens when you pass "a" to your function?
I tested your code and got the expected result. Maybe the problem is related with function pow.
You could write the function simpler without using functions that deal with real numbers.
For example
int strToint( const char str[] )
{
int sum = 0;
for ( ; *str; ++str )
{
sum = 10 * sum + *str - '0';
}
return sum;
}
Take into account that function gets is unsafe. It is better to use function fgets. For example
fgets( str, 20, stdin );
size_t n = strlen( str );
if ( str[n - 1] == '\n' ) str[n - 1] = '\0';
On the first call to pow(10,2) the library's weak pow() returns 99.999... which is truncated to 99 on assignment to j.
Since the first digit is 5, the final sum is 5 less. (100*5 vs 99*5)
If code must use FP functions, best to round before integer assignment
j = round(pow(10,...));
As #Vlad points out, all FP math can be avoided.
--
Floating point functions are not required by C to be accurate. A good pow() function though should have provided an exact answer here, that is why it worked on so many other machines.
For a complete atoi, there are many posts, such as FromStringToInteger

10 element array

My teacher gave an assignment to me. The question is below:=
Write a program that prompts the user to enter 10 double numbers. The program should accomplish the follwing:
a. Store the information in a 10-element array.
b. Display the 10 numbers back to the user.
I could do all of the above in main().
Hint: You should use loops, not hardcode the values 0 through 9. It should be easy to convert your program to accept 1000 numbers instead of 10.
For a bonus mark, do at least one of the tasks (a or b) in a separate function. Pass the array to the function; do NOT use global (extern) variables.
I confused above. I wrote a program in the source code. Am I doing wrong? It is below:=
#include<stdio.h>
int main(void)
{
int number[10];
int i;
for (i = 0; i <10; i++)
printf("%d.\n", i, number[i]);
printf("\n\nPress [Enter] to exit program.\n");
fflush(stdin);
getchar();
return 0;
}
Thanks.
Not too bad so far, I'd like to make the following comments:
if you need to input double numbers, you should probably use double rather than int.
you need a statement (maybe in your current loop but possibly in another loop preceding the current one) which inputs the numbers. Look into scanf for this.
Using %d with printf is for integers, not doubles. You will have hopefully already figured out the format string to used when you looked into scanf above.
Bravo for using the correct int main(void) form and for not including conio.h :-)
Once you've figured those bits out, then you can worry about doing it in a separate function.
Based on the code you have given above, I would suggest reading up on the following:
scanf
functions in C, particularly passing arrays to functions: this link should be good.
Note to OP: If you were able to do (a) and (b) in main(), the code above is not complete. It would be nice the functions you created for getting (a) and (b) above done for getting to the root of your "confusion".
Let me know in case you need more help.
HTH,
Sriram
Try this it may sloves your problem.
#include<stdio.h>
int main(void)
{
double number[10];
int i;
printf("Enter double numbers:");
for (i = 0; i <10; i++)
scanf("%lf",&number[i] );
printf("The numbers you entered are:");
for (i = 0; i <10; i++)
printf("%lf\n",number[i] );
return 0;
}

Simply C loop is driving me nuts

So I have only ever programmed in c++, but I have to do a small homework that requires the use of c. The problem I encountered is where I need a loop to read in numbers separated by spaces from the user (like: 1 5 6 7 3 42 5) and then take those numbers and fill an array.
the code I wrote is this:
int i, input, array[10];
for(i = 0; i < 10; i++){
scanf("%d", &input);
array[i] = input;
}
EDIT: added array definition.
any suggestions or hints would be very highly appreciated.
Irrespective of whatever is wrong here, you should quickly learn to NEVER write code that does not check the return value from any API call that you make. scanf returns a value, and you have to be interested in what it says. If the call fails, your logic is different, yes?
Perhaps in this case it would tell you what's going wrong. The docs are here.
Returns the number of fields
successfully converted and assigned;
the return value does not include
fields that were read but not
assigned. A return value of 0
indicates that no fields were
assigned.
This code working good.
If your numbers is less than 10, then you must know how many numbers is before you start reading this numbers, or last number must be something like 0 to terminate output then you can do while(true) loop, but for dynamically solution you must read all line into string and then using sscanf to reading numbers from this string.
You need the right #include and a proper main. The following works for me
#include <stdio.h>
int main(void) {
/* YOUR CODE begin */
int i, input, array[10];
for (i = 0; i < 10; i++) {
scanf("%d", &input);
array[i] = input;
}
/* end of YOUR CODE */
return 0;
}
i'm not a c programmer but i can suggest an algorithm which is to use scanf("%s",&str) to read all the input into a char[] array then loop over it and test using an if statment if the current char is a space, if it is then add the preceeding number to the array

Resources