Int pointers having weird behavior in C - c

void main(){
int digits[21]; //this was initialized so that every element is 0 by looping over every element and setting it to 0
char input[20];
scanf("%s", input);
parseDigits(digits, input);
}
void parseDigits(int* digits, char *string){
char *end = string + strlen(string) -1;
int i;
for (i = 0; i < strlen(string) - 1; i++, end--){
int *digit = digits + i;
printf("%d", *digit);
*digit += charToDigit(*end);
if (*digit >= 10){ //carry one
*digit -= 10;
digit++;
*digit += 1;
}
}
}
Prints an excessively large integer, instead of 0, which is the expected output. I don't understand since
digits + i
should still be within the range of the array.

There can be other issues, but from first glance you have not initialized your array properly, which should have been done like:
int digits[21] = { 0 };

Related

Can you put int variable into string in c?

Can you put an integer from a variable, for example:
int i=17;
char array[]= i;
and now i want to have
array[3]= {1,7,\0}
I know it doesn't work this way but i dont know how to do it without some special functions, which i dont want to use. Thank you for your help.
this is what i came up with:
char array[];
int counter = 172; //the number i want to put into string
int i= 0;
int p=0;
float c = counter;
int k=0, g=0, h=0;
while(counter !=0){
counter = counter /10;
c= c/10;
p++;
}
while(p !=0){
c=c*10;
k=c;
h= k-g;
g=k*10;
array[i] = h;
i++;
p--;
}
array[i]= '\0';
Use sprintf(buffer, "%d", i);
Make sure that buffer is long enough to contain any possible number-string and the terminating \0 byte.
sprintf accepts everything that printf does, but sends its output to a string buffer instead of STDOUT.
If you really don't want to use sprintf, then here is a sample code snippet for you.
#define BASE 10
#define MAXLEN 10
int val = 153;
char valstr[MAXLEN];
//Reverse the int
int valcpy = val;
int valrev = 0;
while(valcpy) {
valrev *= BASE;
valrev += valcpy % BASE;
valcpy /= BASE;
}
//Convert to string
int i = 0;
while(valrev) {
valstr[i] = valrev % BASE + '0';
valrev /= BASE;
i++;
}
valstr[i] = '\0';
printf("%d = %s", val, valstr); //prints 153 = 153

sprintf to reverse an int and store as char

I"m trying to store int array as a str and display it but in the reverse order.
Its only while printing the str that i get junk.
What is wrong in my code?
int main() {
int a[] = { 1, 2, 3 }; // Output should be 321 (char)
int size = sizeof(a) / sizeof(int);
char str[size + 1];
int i;
for (size = size - 1; size >= 0; size--) {
sprintf(&str[size], "%d", a[size]);
//printf("%c\n", str[size]);
}
printf("%s\n", str); // I get garbage.
}
I modified your solution with several bug fixes. For starters, you can't assume that your integer array will only hold single digit values.
And that for loop as you have it:
for(size=size-1;size >= 0;size--)
Is very suspicious looking. (the index variable is the thing its based off?)
Simple solution
This is likely what you meant:
for(i = 0; i < size; i++) {
sprintf(&str[i],"%d", a[size-1-i]);
}
str[size] = '\0';
Or this:
str[size] = '\0';
for(i = size-1; i <= 0; i--) {
sprintf(&str[i],"%d", a[size-1-i]);
}
Better solution
I'm not sure what you are expecting to do if an integer within the a array is negative. So the - sign will just get inserted into str inplace.
The solution I have will first count how many chars are needed for each integer in a. Then it will allocate the str buffer with that length (+1 for null char).
Then we make use of the return value from sprintf to figure out where to concatenate onto. We could use strcat, but this is likely faster.
int main() {
int j = 0;
int a[] = { 1,2,3 }; // Output should be 321 (char)
int size = sizeof(a) / sizeof(int);
int length = 1; // +1 for final null char
// Count the size of characters needed for each integer
// Do a dummy sprintf and use its return value to figure out how many chars are needed
for (int i = 0; i < size; i++) {
char tmp[sizeof(int) * 5]; // sizeof(int)*5 is big enough to hold any integer including a negative value
length += sprintf(tmp, "%d", a[i]); // utilize the return value from sprintf and add it to the running length
}
char str[length];
str[0] = '\0'; // initially null terminate our string
// reverse print chars from a into str
for (int i = 0; i < size; i++) { // use i as index variable, not size
j += sprintf(str + j, "%d", a[size - 1 - i]);
}
printf("%s\n", str);
}
Alternative solution, closer to original posts, and clearly not trying to address the general problem (assume values are single digit):
int a[]={1,2,3}; // Output should be 321 (char)
int size = sizeof(a)/sizeof(int);
char str[size+1];
for(int i=0; i<size ; i++) {
str[size-1-i] = ‘0’ + a[i];
}
str[size] = 0;
printf("%s\n", str); // I get garbage.
}
Taking advantage of the assumed input value, converting each int to character representation at the reverse position.

How to handle negative integer when converting them to strings? [closed]

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 4 years ago.
Improve this question
I need to convert integer to a string, be it negative or positive.
So far i able to convert positive integers to strings using the following code.
But not the negative ones. How can i handle them properly to convert them to strings.
Here is the code that i was using.
Thanks
Rajat!
/*
* C Program which Converts an Integer to String & vice-versa
*/
#include <stdio.h>
#include <string.h>
#include <math.h>
void tostring(char [], int);
int main()
{
char str[10];
int num, result;
printf("Enter a number: ");
scanf("%d", &num);
tostring(str, num);
printf("Number converted to string: %s\n", str);
return 0;
}
void tostring(char str[], int num)
{
int i, rem, len = 0, n;
if(num<0)
{
n=(-1)*(num);
}
else
{
n=num;
}
while (n != 0)
{
len++;
n /= 10;
}
for (i = 0; i < len; i++)
{
rem = num % 10;
num = num / 10;
str[len - (i + 1)] = rem + '0';
}
str[len] = '\0';
}
Before doing anything else, see if n is negative. If it is, start the output with the sign - (make sure len is also one more than it would be otherwise, and that your stringification starts one character later), make n positive, and continue as you were doing it before.
You have to be really wary of "corner-case" like many other have said :
You can't have the positive value of a negative int in an int
The range value of an int is [MIN; +MIN -1], like –2,147,483,648 to 2,147,483,647 for a 4 byte int.
So, if you have –2,147,483,648 and you *-1, you will not have 2,147,483,648 since it will overflow the int capacity
Your loop for finding the len of int is "bad", because you don't take negative number in count (but I suppose this is the purpose of this post) and you don't take car of the corner case 0 ("len" value is 0 but must be 1).
So, how can you make this function ?
1 : Fix the int len calculation
size_t len = 1;
for (int n = number; n <= -10 || 10 <= n; n /= 10) {
++len;
}
2 : Fix the "digit to char" loop
for (size_t i = 0; i < len; ++i) {
str[len - i - 1] = abs(number % 10) + '0';
number /= 10;
}
str[len] = '\0';
There. The only thing that left is to put "-" in the beginning and have an offset for negative case number.
You can have an offset variable (fix the "digit to char loop" if you use it) or you can simply do "++str".
There, you can do the function on your own now, I pratically gived you the answer.
On a funny note, you can skip the "abs" function if you simply do the following :
void tostring(char *str, int number)
{
char *digit = "9876543210123456789" + 9;
size_t len = 1;
if (number < 0) {
// TODO : Put '-' in the first case
// TODO : Make str to be *str[1]
}
for (int n = number; n <= -10 || 10 <= n; n /= 10) {
++len;
}
for (size_t i = 0; i < len; ++i) {
str[len - i - 1] = digit[number % 10];
number /= 10;
}
str[len] = '\0';
}
If you don't understand how this work, take your time and read how pointer work (especially pointer arithmetic).
I have solved the issue by the help from #Amadan .
Here is the code that i am using. Please feel free to tell me a more better way to solve this issue.
Thanks
Rajat
/*
* C Program which Converts an Integer to String & vice-versa
*/
#include <stdio.h>
#include <string.h>
#include <math.h>
void tostring(char [], int);
int main()
{
char str[10];
int num, result;
printf("Enter a number: ");
scanf("%d", &num);
tostring(str, num);
printf("Number converted to string: %s\n", str);
return 0;
}
void tostring(char str[], int num)
{
int i, rem, len = 0, n;
bool flag=0;
if(num<0)
{
n=-num;
flag=1;
}
else
{
n=num;
flag=0;
}
while (n != 0)
{
len++;
n /= 10;
}
if(flag==1)
{
num=-1*num;
str[0]='-';
}
for (i = 0; i < len; i++)
{
rem = num % 10;
num = num / 10;
if(flag==1)
{
str[len - (i)] = rem + '0';
}
else
{
str[len - (i + 1)] = rem + '0';
}
}
if(flag==1)
{
str[len+1] = '\0';
}
else
{
str[len] = '\0';
}
}
Just use sprintf function as below,
sprintf(str,"%i",num);
So the modified code will be,
#include <stdio.h>
#include <string.h>
#include <math.h>
void tostring(char [], int);
int main()
{
char str[10];
int num, result;
printf("Enter a number: ");
scanf("%d", &num);
//tostring(str, num);
sprintf(str,"%i",num);
printf("Number converted to string: %s\n", str);
return 0;
}
void tostring(char str[], int num)
{
int i, rem, len = 0, n;
n =num;
while (n != 0)
{
len++;
n /= 10;
}
for (i = 0; i < len; i++)
{
rem = num % 10;
num = num / 10;
str[len - (i + 1)] = rem + '0';
}
str[len] = '\0';
}
Hope this helps.
Here you have the function which works with any base (you need just to find enough chars to represent digits) but it will not work in one corner case (can you find the case?)
static const char Digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUWXYZ";
static char *reverse(char *s, size_t len)
{
size_t pos;
for(pos = 0; pos < len / 2; pos++)
{
char tmp = s[pos];
s[pos] = s[len - pos - 1];
s[len - pos - 1] = tmp;
}
return s;
}
char *toString(char *buff, int n, unsigned base)
{
int saved = n;
char *savedbuff = buff;
n = n < 0 ? -n : n; // <= there is one number which will cause problems. Which one?
do
{
*buff++ = Digits[n % base];
n /= base;
}while(n);
if(saved < 0) *buff++ = '-';
*buff = 0;
return reverse(savedbuff, buff - savedbuff);
}
int main()
{
char buff[50];
printf("%s\n", toString(buff, -255,12)); // 12 base :)
printf("%s\n", toString(buff, -976,10)); // 10 base
printf("%s\n", toString(buff, -976,8)); // or maybe octal ?
return 0;
}

Count and get integers from a string using C

I am self teaching C programming.
I am trying to count number of int present in given string which are separated by space.
exp:
input str = "1 2 11 84384 0 212"
output should be: 1, 2, 11, 84384, 0, 212
total int = 6
When I try. It gives me all the digits as output which make sense since I am not using a right approach here.
I know in python I can use str.split (" ") function which can do my job very quickly.
But I want to try something similar in C. Trying to create my own split method.
#include <stdio.h>
#include <string.h>
void count_get_ints(const char *data) {
int buf[10000];
int cnt = 0, j=0;
for (int i=0; i<strlen(data); i++) {
if (isspace(data[i] == false)
buf[j] = data[i]-'0';
j++;
}
printf("%d", j);
}
// when I check the buffer it includes all the digits of the numbers.
// i.e for my example.
// buf = {1,2,1,1,8,4,3,8,4,0,2,1,2}
// I want buf to be following
// buf = {1,2,11,84384,0,212}
I know this is not a right approach to solve this problem. One way to keep track of prev and dynamically create a memory using number of non space digits encountered.
But I am not sure if that approach helps.
You want to build your number incrementally until you hit a space, then put that into the array. You can do this by multiplying by 10 then adding the next digit each time.
void count_get_ints(const char *data) {
int buf[10000];
int j = 0;
int current_number = 0;
// Move this outside the loop to eliminate recalculating the length each time
int total_length = strlen(data);
for (int i=0; i <= total_length; i++) {
// Go up to 1 character past the length so you
// capture the last number as well
if (i == total_length || isspace(data[i])) {
// Save the number, and reset it
buf[j++] = current_number;
current_number = 0;
}
else {
current_number *= 10;
current_number += data[i] - '0';
}
}
}
I think strtok will provide a cleaner solution, unless you really want to iterate over every char in the string. It has been a while since I did C, so please excuse any errors in the code below, hopefully it will give you the right idea.
#include <stdio.h>
#include <stdlib.h>
int main() {
char str[19] = "1 2 11 84384 0 212";
const char s[2] = " ";
char *token;
int total;
total = 0;
token = strtok(str, s);
while (token != NULL) {
printf("%s\n", token);
total += atoi(token);
token = strtok(NULL, s);
}
printf("%d\n", total);
return 0;
}
You can check the ascii value of each character by doing c-'0'. If it's between [0,9], then it's an integer. By having a state variable, when you're inside an integer by checking if a given character is a number of space, you can keep track of the count by ignoring white space. Plus you don't need a buffer, what happens if data is larger than 10,000, and you write pass the end of the buffer?, undefined behavior will happen. This solution doesn't require a buffer.
Edit, the solution now prints the integers that are in the string
void count_get_ints(const char *data) {
int count = 0;
int state = 0;
int start = 0;
int end = 0;
for(int i = 0; i<strlen(data); i++){
int ascii = data[i]-'0';
if(ascii >= 0 && ascii <= 9){
if(state == 0){
start = i;
}
state = 1;
}else{
//Detected a whitespace
if(state == 1){
count++;
state = 0;
end = i;
//Print the integer from the start to end spot in data
for(int j = start; j<end; j++){
printf("%c",data[j]);
}
printf(" ");
}
}
}
//Check end
if(state == 1){
count++;
for(int j = start; j<strlen(data); j++){
printf("%c",data[j]);
}
printf(" ");
}
printf("Number of integers %d\n",count);
}
I believe the standard way of doing this would be using sscanf using the %n format specifier to keep track of how much of the string is read.
You can start with a large array to read into -
int array[100];
Then you can keep reading integers from the string till you can't read anymore or you are done reading 100.
int total = 0;
int cont = 0;
int ret = 1;
while(ret == 1 && total < 100) {
ret = sscanf(input, "%d%n", &array[total++], &cont);
input += cont;
}
total--;
printf("Total read = %d\n", total);
and array contains all the numbers read.
Here is the DEMO
Example using strtol
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <errno.h>
#include <ctype.h>
int count_get_ints(int output[], int output_size, const char *input) {
const char *p = input;
int cnt;
for(cnt = 0; cnt < output_size && *p; ++cnt){
char *endp;
long n;
errno = 0;
n = strtol(p, &endp, 10);
if(errno == 0 && (isspace((unsigned char)*endp) || !*endp) && INT_MIN <= n && n <= INT_MAX){
output[cnt] = n;
while(isspace((unsigned char)*endp))
++endp;//skip spaces
p = endp;//next parse point
} else {
fprintf(stderr, "invalid input '%s' in %s\n", p, __func__);
break;
}
}
return cnt;
}
int main(void) {
const char *input = "1 2 11 84384 0 212";
int data[10000];
int n = sizeof(data)/sizeof(*data);//number of elements of data
n = count_get_ints(data, n, input);
for(int i = 0; i < n; ++i){
if(i)
printf(", ");
printf("%d", data[i]);
}
puts("");
}
Assuming you don't have any non-numbers in your string, you can just count the number of spaces + 1 to find the number of integers in the string like so in this pseudo code:
for(i = 0; i < length of string; i++) {
if (string x[i] == " ") {
Add y to the list of strings
string y = "";
counter++;
}
string y += string x[i]
}
numberOfIntegers = counter + 1;
Also, this reads the data between the white spaces. Keep in mind this is pseudo code, so the syntax is different.

Exception thrown: read access violation

i'm a beginner and my english is not well so sorry first. im trying to sum the numbers in a string (for a14fg5pk145 it returns 14+5+145), and it doesn't work:
"Exception thrown: read access violation.
str was 0x61."
this i my code:
void main()
{
int x, i;
char* pp;
char buffer[SIZE];
printf("Please enter numbers and letters:\n");
gets(buffer);
pp = buffer;
x = SumStr(*pp);
printf("%d", x);
}
int SumStr(char* str)
{
int sum=0, num=0, flag = 0;
while ((*str) != '\0')
{
while (((*str) > '1') && ((*str) < '9'))
{
if (flag == 0)
{
num += (*str);
flag = 1;
}
else if (flag == 1)
num = num * 10 + (*str);
str++;
}
if (flag == 0)
str++;
sum += num;
num = 0;
flag = 0;
}
return sum;
}
First problem with your code which is causing Exception.
x = SumStr(*pp);
it should be
x = SumStr(pp);
Because you should pass address of the string pointer not its first character by attaching asterix.
Second Issue that will not make it work is.
num += (*str);
and
num = num * 10 + (*str);
By (*str) you are actually adding the character ascii value instead of number.
This will solve the problem by changing the ascii value to number.
num += (*str) - '0';
num = num * 10 + (*str) - '0';
This may serve your purpose
#include<stdio.h>
#include<string.h>
int main()
{
int i, sum = 0, store;
char str[] = "a14fg5pk145asdasdad6";
int length = strlen(str);
for(i = 0; i < length; i++) {
store = 0;
while(isdigit(str[i])) {
store = (store * 10) + (str[i] - '0');
i++;
}
sum += store;
}
printf("%d\n", sum);
return 0;
}
output :
170
Pass pp, not *pp, to the function SumStr. *pp has the type char, and the function expects char *. In fact, you do not even need pp at all, just pass the buffer as the parameter.
Also:
Never use gets(). Because it is impossible to tell without knowing the
data in advance how many characters gets() will read, and because
gets() will continue to store characters past the end of the buffer, it
is extremely dangerous to use. It has been used to break computer
security. Use fgets() instead.

Resources