So I have seen that some people do not recommend using String literals to create a char in C. However, I have found this to be the most useful method and I have a char set as
char a[] = "456";
I understand that the memory is fixed in this data type. However, in my assignment I believe that I need to be able to reallocate memory for my char value since I am adding integers that are represented as strings. For example:
char b[] = "500";
char c[] = "501";
//add function for adding b and c. have a char d[] equal to "1000".
I am using long addition to accomplish this. I have tried experimenting with the realloc function but it did not work. How would I continuously append new characters onto a string?
For your assignment, you must define a destination array with enough space to hold the result, which for an addition is easy to determine: it is the length of the longest argument plus one character for a possible extra digit plus one character for the null terminator.
You can allocate this array with malloc() and return a pointer.
Here is an example:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *bigadd(const char *a, const char *b) {
size_t alen = strlen(a);
size_t blen = strlen(b);
size_t clen = (alen > blen) ? alen : blen;
size_t mlen = (alen > blen) ? blen : alen;
char *c = malloc(clen + 2);
if (c != NULL) {
size_t i;
int carry = 0;
c[clen] = '\0';
for (i = 1; i <= mlen; i++) {
carry += a[alen - i] - '0' + b[blen - i] - '0';
c[clen - i] = '0' + carry % 10;
carry /= 10;
}
for (; i <= alen; i++) {
carry += a[alen - i] - '0';
c[clen - i] = '0' + carry % 10;
carry /= 10;
}
for (; i <= blen; i++) {
carry += b[blen - i] - '0';
c[clen - i] = '0' + carry % 10;
carry /= 10;
}
if (carry) {
memmove(c + 1, c, clen + 1);
c[0] = (char)('0' + carry);
}
}
return c;
}
int main(int argc, char *argv[]) {
const char *a = argc > 1 ? argv[1] : "123456890123456890123456890";
const char *b = argc > 2 ? argv[2] : "2035864230956204598237409822324";
char *c = bigadd(a, b);
printf("%s + %s = %s\n", a, b, c);
free(c);
return 0;
}
so the way I see it is by typing:
char a[] = "456";
you initialise a character array of size 4 (3 chars +'\0'). storing anything longer in the same array could cause an undefined behavior and must be avoided. long story short: you can modify the value of this array, as long as the size of it doesn't change. You can initialise an array like this:
char a[100] = "456";
to leave some extra space for any possible additions to the string, but that's about it, since a size of the array is known at compiling, and doesn't ever change.
also please note that this won't work:
char * a = "456";
it's a read-only string literal which cannot be modified or realloced.
PS: I'm a novice, please correct me if I'm wrong!
Related
I'm trying to create a function that will receive an array of strings and the size and will return a string made of the biggest ASCII value's letter of each word, and the size of the string has to be precised and I'm not allowed using operator [](which is my main issue).
so for:
char *strArr[SIZE] = { "hello", "and", "good", "morning" };
the function shall return a string with the word
"onor"
.
So i thought of creating a double for loop, first one will lead me into the location of each word in the array and the inside one will help me go through each word.
currently I'm having trouble finding the right format with my pointers to actually go through the letters of my first word.
I'm aware i haven't checked if my memory allocation is valid and also didn't free my memory yet as I'm trying to figure out whats wrong first.
char *bigLetters(char *str[], int size)
{
char *strNew = (char *)malloc((size + 1) * sizeof(char));
char max = 'a';
for (int i = 0; i < size; i++)
{
for (int j = 0; (*(str + i)+j) != NULL; j++)
{
if ((*(str + i) + j) >= max)
{
max = (*(str + i) + j);
}
}
*(strNew + i) = max;
}
*(strNew +(size+1)) = NULL;
return *(strNew);
}
void main()
{
char *strArr[SIZE] = { "hello", "and", "good", "morning" };
char *res = bigLetters(strArr, SIZE);
printf("The new string is --> %s\n", res);
system("pause");
}
It will be easier to use the pointers if you separate the string pointer from its character pointer. Also, the max needs to be reset for each string, and you were writing the final string terminator outside of the memory allocated. You also use NULL where you should be using the character '\0'.
Finally the function was returning the first character of the new string (which I later free).
#include <stdio.h>
#include <stdlib.h>
#define SIZE 4
char *bigLetters(char *str[], int size)
{
char *strNew = malloc(size + 1); // no cast or sizeof necessary
for (int i = 0; i < size; i++)
{
char ch;
char max = 'a'; // moved inside loop
char *ptr = *(str + i); // use a separate pointer
for (int j = 0; (ch = *(ptr + j)) != '\0'; j++) // pull out the character
{
if (ch > max) // >= is not necessary
{
max = ch;
}
}
*(strNew + i) = max;
}
*(strNew + size) = '\0'; // correct the bounds error
return strNew; // just the pointer not its target
}
int main(void) // correct signature
{
char *strArr[SIZE] = { "hello", "and", "good", "morning" };
char *res = bigLetters(strArr, SIZE);
printf("The new string is --> %s\n", res);
free(res); // clean up
system("pause");
}
Program output
The new string is --> onor
Press any key to continue . . .
If you didn't impose odd and unhelpful restrictions upon your coding, you'd be able to quickly see the problems with your code or even avoid making them in the first place. The problem is that the following statement makes no sense - you're comparing a char * with a char as you're only de-referencing str once.
if ((*(str + i) + j) >= max)
This is the same as writing
if ((str[i] + j) >= max)
which you can see the obvious mistake since what you're trying to write is the equivalent of
if ((str[i][j]) >= max)
which would be
if (*(*(str + i) + j) >= max)
Your compiler should be throwing up warnings because comparing between a pointer and an integer is rarely something you'd want to do.
You can use pointers as position indicators and advance them as needed.
#include <stdio.h>
#include <stdlib.h>
#define SIZE 4
char
biggest_ascii(char* str)
{
char c = 0;
int i;
for (i = 0; *str; str++)
if (*str > c)
c = *str;
return c;
}
int
main()
{
int i;
char* strArr[SIZE] = {"hello", "and", "good", "morning"};
char** ppch;// current string
char res_str[SIZE + 1] = {0};/* resulting string,
initilized to 0 to be 0-terminated */
char* pch;// current char position
for (i = 0, ppch = strArr, pch = res_str; i < SIZE; i++, ppch++, pch++)
*pch = biggest_ascii(*ppch);
printf("%s\n", res_str);
return 0;
}
First, (*(str + i)+j) isn't the good way.
You could replace all
(*(str + i) + j)
by :
str[i][j]
Then, you need to reset the max to "a", because it's 'o' when you leave the loop, so your condition become str[i][j] >= o which is not what you want. Do it before the second for.
And I would have used while instead of for for the first loop.
I edited your code and this version is working fine for me :
#include <stdlib.h>
char *bigLetters(char *str[], int size)
{
char *strNew = (char *)malloc((size + 1) * sizeof(char));
int i = 0;
while (i < size) {
char max = 'a';
for (int j = 0; str[i][j]; j++) {
if (str[i][j] >= max) {
max = str[i][j];
}
}
strNew[i] = max;
i++;
}
strNew[i] = '\0';
return strNew;
}
void main()
{
char *strArr[5] = { "hello", "and", "good", "morning"};
char *res = bigLetters(strArr, 4);
printf("The new string is --> %s\n", res);
return 0;
}
str[i] is equivalent to *(str + i) and str[i][j] is equivalent to *(*(str + i) + j).
In your code you are using (*(str + i) + j) which is incorrect.
When char *[] passed to function, it will decay to char **. So, in bigLetters(), you can give char **str as the parameter. Also, it is inline with you requirement - not allowed using operator [].
Instead of hardcoding the dimension SIZE in char *strArr[SIZE], you can give the empty [] and let the compiler assign the dimension based on the size of initializer. In your case, size of initializer is 4 as you have given 4 strings in the strArr initializer. You can compute the size of strArr like this:
sizeof(strArr)/sizeof(strArr[0]);
You can do:
#include <stdio.h>
#include <stdlib.h>
char *bigLetters(char **str, size_t size) {
char *strNew = calloc(size + 1, 1); // sizeof(char) is always 1
// calloc will initialize all bytes in the allocated storage to zero.
// You dont need to add the null terminating character at the end of strNew
if (strNew == NULL)
exit(EXIT_FAILURE);
for (size_t i = 0; i < size; i++) {
for (size_t j = 0; *(*(str + i)+j) != '\0'; j++) {
if (*(*(str + i) + j) > *(strNew + i)) {
// You can directly fill the allocated memory with biggest ASCII
*(strNew + i) = *(*(str + i) + j);
}
}
}
return strNew;
}
int main(void) {
char *strArr[] = { "hello", "and", "good", "morning" };
char *res = bigLetters(strArr, sizeof(strArr)/sizeof(strArr[0]));
if (res != NULL) {
printf("The new string is --> %s\n", res);
free (res);
}
else
printf("bigLetters returned NULL\n");
return 0;
}
Note that void return type main() is not as per standard. Instead, you should use int as return type of main().
ANSI c on OSX 10.13.6
Apple LLVM version 9.1.0 (clang-902.0.39.2)
Target: x86_64-apple-darwin17.7.0
Thread model: posix
I'm learning c
This is a function that manually (character-by-character) adds two character strings representing large numbers (that exceed the unsigned long long or double size).
It functions fine with any two strings 14 or less characters long, but segmentation fault 11 with any strings greater than 14 chars.
Changing the string's memory allocation method seems to have no effect (I.e. from char[15] addend1; // not a ptr to char *addend1 = (char *) malloc(sizeof(char) * (16) ); // pointer
One things that's curious, is that it seems to segfault on the ...
for (int j = maxlength - 1 ; j >= 0; j--)
... prior to accessing either of addend1 or addend2, but I'm not able to find an error there or change it to prevent the segfault.
Am I misreading where the error arises, or could it be related to the for loop?
Successful run (less than 15 chars)
maxlength = 14
char *sum = (char *) malloc(sizeof(char) * (maxlength + 1) ) ... DONE
for (int i = 0; i < (maxlength); i++) { sum[i] = '0'; } ... DONE
Start adding individual ints from end (right side) ...
13 ...12 ...11 ...10 ...9 ...8 ...7 ...6 ...5 ...4 ...3 ...2 ...1 ...0 ...main.sum = 28147497671064
UNSuccessful run (15 chars)
maxlength = 15
char *sum = (char *) malloc(sizeof(char) * (maxlength + 1) ) ... DONE
for (int i = 0; i < (maxlength); i++) { sum[i] = '0'; } ... DONE
Start adding individual ints from end (right side) ...
Segmentation fault: 11
MAIN.c
#include <stdio.h>
#include <stdlib.h>
#include "../../c-library/include/addViaStrings.h"
int main(void) {
// s[0] = 72; s[1] = 101; s[2] = 108; s[3] = 108; s[4] = 111; s[5] = 32; s[6] = 87; s[7] = 111; s[8] = 114; s[9] = 108; s[10] = 100; s[11] = 0;
// WORKS
// char s1[] = "14073748835532";
// char s2[] = "14073748835532";
// FAILS
char s1[] = "140737488355328";
char s2[] = "140737488355328";
char *sum = addNumericStrings(&s1, &s2);
printf("main.sum = %s\n", sum);
}
addViaStrings.h
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
char* addNumericStrings(char *s1, char *s2);
char leftPad(char *result, char *s, int maxlength);
int findMaxLength(char *s1, char *s2);
char* addNumericStrings(char *s1, char *s2){
// Find the length of the greater of the two
int maxlength = findMaxLength(s1, s2);
printf("maxlength = %d\n", maxlength); //333
///////////////////////////////////////////////
// Using malloc instead of char[maxlength] seems to have NO EFFECT on the issue
// char addend1[maxlength]; // not a pointer
char *addend1 = (char *) malloc(sizeof(char) * (maxlength + 1) );
addend1[maxlength + 1] = 0; // end flag
// char addend2[maxlength]; // not a pointer
char *addend2 = (char *) malloc(sizeof(char) * (maxlength + 1) );
addend2[maxlength + 1] = 0; // end flag
// Allocate sum pointer
printf("char *sum = (char *) malloc(sizeof(char) * (maxlength + 1) ) ... "); //333
char *sum = (char *) malloc(sizeof(char) * (maxlength + 1) );
printf("DONE\n"); //333
// General use vars
int a1, a2, total;
int carry = 0;
// Prepare the strings for manual addition. Pad the left with char 0s
leftPad(addend1, s1, maxlength);
leftPad(addend2, s2, maxlength);
// Buffer sum with zeros
sum[maxlength + 1] = 0; // end flag
printf("for (int i = 0; i < (maxlength); i++) { sum[i] = '0'; } ... "); //333
for (int i = 0; i < (maxlength); i++) { sum[i] = '0'; } // Fill w/ 0s
printf("DONE\n"); //333
// Run the manual addition
// Start adding individual ints from end (right side)
printf("Start adding individual ints from end (right side) ...\n"); //333
// maxlength -1 because(I think) the termination char takes 2 bytes
// If I use (maxlength) instead of (maxlength -1) I get a weird
// question mark char at the end of returnsum
for (int j = maxlength - 1 ; j >= 0; j--) {
///////////////////////////////////////////
// The segfault seems to happen BEFORE accessing addend1 or addend2
printf("%d ...", j); // 333 This DOES NOT print
///////////////////////////////////////////
a1 = addend1[j] - '0'; // Convert to int
a2 = addend2[j] - '0'; // Convert to int
total = (a1 + a2 + carry);
carry = 0;
if ( total >= 10){
carry += 1;
total -= 10;
}
sum[j + 1] = '0'+total; // convert to ascii value for numbers (adding 48)
}
sum[0] = '0' + carry; // add last carry to start of num always, even if 0
// Before returning, truncate leading zeros
char *returnsum = (char *) malloc(sizeof(char) * (strlen(sum) + 1) );
int sum_i = 0;
int returnsm_i = 0;
// bool truncate = true; // Find out why this wont compile
int truncate = 1; // true
while (1){
// if order is important here
if (sum[sum_i] == '\0') { break; } // we're done
if (sum[sum_i] == '0' && truncate == 1) { sum_i += 1; continue; } // 1 is true
// if a num, Stop truncating 0s but DO continue adding numbers
if (sum[sum_i] != '0') { truncate = 0; } // 0 is false
returnsum[returnsm_i] = sum[sum_i];
returnsm_i += 1;
sum_i += 1;
}
return returnsum;
}
char leftPad(char *result, char *s, int maxlength){
int slength = strlen(s);
// buffer with zeros, not '\0's
for (int i = (maxlength); i >= 0; i--){ result[i] = '0'; }
// right fill result with s
for (int j = 0; j <= slength; j++){
int index = ((maxlength - slength) + j);
result[index] = s[j];
}
result[maxlength + 1] = 0;
}
int findMaxLength(char *s1, char *s2){
// int length1 = findEndLength(s1);
// int length2 = findEndLength(s2);
int length1 = strlen(s1);
int length2 = strlen(s2);
int maxlength;
(length1 > length2) ? (maxlength = length1) : (maxlength = length2);
return maxlength;
}
The issue was I was trying to access the sum string as if it was one position longer than the addends strings, but I had declared it as the same length (I.e. maxlength + 1). So I was attempting to access one position past the actual sum array.
This was a somewhat hidden problem, because it was not until the length of sum needed to be greater than 15, that this access error stepped into disallowed memory space, resulting in a segfault.
Details
Because the sum of two addends could conceivably require at least one additional position in the array if the sums carried over a one (I.e. 999 + 999 = 1998), the sum string needs to be one array position longer than the addends.
If the addends were 3 digits long (length of array = 4) then the sum needed to be 4 digits long (array length = 5).
// Correct code if "maxlength" (number of actual digits in string) = 14
char *addend1 = (char *) malloc(sizeof(char) * (maxlength + 1) ); // +1 To include termination byte
char *addend2 = (char *) malloc(sizeof(char) * (maxlength + 1) ); // +1 To include termination byte
char *sum = (char *) malloc(sizeof(char) * (maxlength + 2) ); // +2 To include termination byte, AND an extra char at the front
...so that the final actual digit character of sum is accessed via maxlength + 1
CORRECTED CODE
NOTE: Because calculating against maxlength as the number of digits (versus the length of the entire array including terminator) was confusing - as well as considered bad form, I have since learned - the following final code has been simplified to use more intuitive variables.
#include <stdio.h>
#include <stdlib.h>
char* addIntsAsStrings(char *s1, char *s2);
char* addIntsAsStrings(char *s1, char *s2){
// Find the length of the greater of the two
int length1 = strlen(s1);
int length2 = strlen(s2);
int addendDigits;
(length1 > length2) ? (addendDigits = length1) : (addendDigits = length2);
// We need separate strings of so they can be buffered with zeros
// Create the string for the addends and buffer with zeros.
char addend1[addendDigits + 1];
char addend2[addendDigits + 1];
for (int i = 0; i < (addendDigits) ; i++){ // "<" not "<="
addend1[i] = '0'; // buffer w/ 0s
addend2[i] = '0'; // buffer w/ 0s
} // buffer w/ 0s
addend1[addendDigits] = '\0'; // terminate
// put s1 and s2 into buffered addends strings
int s1_index = (strlen(s1) - 1);
int s2_index = (strlen(s2) - 1);
for (int i = (addendDigits - 1); i >= 0; i--){ //Start at back of addend
if ( s1_index >= 0) { addend1[i] = s1[s1_index]; }
if ( s2_index >= 0) { addend2[i] = s2[s2_index]; }
s1_index -= 1;
s2_index -= 1;
}
// Allocate sum pointer. The sum pointer needs to be ONE char
// longer than the addends, in the event that the addends need
// to carry a final one to the front. I.e. 999 + 999 = 1998
int sumDigits = addendDigits + 1;
char *sum = (char *) malloc(sizeof(char) * (sumDigits + 1) ); // +1 To include termination byte, AND an extra char at the front
for (int i = 0; i < (sumDigits) ; i++){ // "<" not "<="
sum[i] = '0'; // buffer w/ 0s
}
sum[sumDigits] = '\0';
// Manual addition vars
int a1, a2, total;
int carry = 0;
// Run the manual addition
// Start adding individual ints from end (right side)
for (int j = addendDigits - 1; j >= 0; j--) {
a1 = addend1[j] - '0'; // Convert to int
a2 = addend2[j] - '0'; // Convert to int
total = (a1 + a2 + carry);
carry = 0;
if ( total >= 10){
carry += 1;
total -= 10;
}
// convert to ascii value for numbers (adding 48)
sum[j + 1] = '0'+total; // sum[j + 1] because `sum`is always one index larger than the addends
}
sum[0] = '0' + carry; // add last carry to start of num always, even if 0
// Before returning, truncate leading zeros
char *returnsum = (char *) malloc(sizeof(char) * (strlen(sum) + 1) );
int sum_i = 0;
int returnsm_i = 0;
int truncate = 1; // true
while (1){
// if order is important here
if (sum[sum_i] == '\0') { break; } // we're done
if (sum[sum_i] == '0' && truncate == 1) { sum_i += 1; continue; } // 1 is true
// if a num, Stop truncating 0s but DO continue adding numbers
if (sum[sum_i] != '0') { truncate = 0; } // 0 is false
returnsum[returnsm_i] = sum[sum_i];
returnsm_i += 1;
sum_i += 1;
}
return returnsum;
}
I've written a function called safecat that adds one string (called ct) to the end of another string (called s).
The resulting new s is then returned.
In the main function my task is to check if my function worked the intended way, and if so, then print the result of my function safecat.
The problem I have is that when I assign the return value of safecat to another char-string (in this case str) in my main function, the stuff in str which comes from ct is just garbage.
I don't understand where the problem is, if I just do printf("%s", safecat(s, ct)); I get the correct result.
Here you see my code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *safecat(char *s, const char *ct);
int main()
{
char s[] = "Twin";
const char ct[] = "Peaks";
char *str = safecat(s, ct);
if(str == NULL){
printf("Error in function!");
return 1;
}
printf("\n%s\n", str);
return 0;
}
char *safecat(char *s, const char *ct){
int i, k, j = 0;
int max_count = strlen(s) + strlen(ct) + 1;
for(i = strlen(s); i < max_count; i = i + sizeof(char)){
*(s + i) = (char *) malloc((strlen(s) + strlen(ct) + 1) * sizeof(char));
if(!(s + i)){
for(k = strlen(s) / sizeof(char); k < i; k++){
free(*(s + k));
}
return NULL;
}
*(s + i) = *(ct + j);
j++;
}
return s;
}
I think the error happens when I assign safecat to str.
When I print out str I get "TwinP' a" instead of "TwinPeaks".
Thanks for helping!
You can not change the size of the array
char s[] = "Twin";
in the function using malloc.
And in any case this loop
for(i = strlen(s); i < max_count; i = i + sizeof(char)){
*(s + i) = (char *) malloc((strlen(s) + strlen(ct) + 1) * sizeof(char));
if(!(s + i)){
for(k = strlen(s) / sizeof(char); k < i; k++){
free(*(s + k));
}
return NULL;
}
*(s + i) = *(ct + j);
j++;
}
does not make sense. For example the expression *(s + i) has type char instead of the type char *. And also it is not clear why a memory is allocated in each iteration of the loop.
A correct approach is to allocate dynamically a new array with the size equal to the sum of the sizes of the source arrays plus one and to copy the source arrays in the allocated array.
Here is a demonstrative program that shows how it can be done. Also you should free the allocated memory when the array is not needed any more.
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
char * safecat(const char *s1, const char *s2)
{
char *result = malloc(strlen(s1) + strlen(s2) + 1);
if (result != NULL)
{
char *p = result;
while (*s1) *p++ = *s1++;
do { *p++ = *s2; } while (*s2++);
}
return result;
}
int main( void )
{
char s[] = "Twin";
char ct[] = "Peaks";
char *str = safecat(s, ct);
if (str == NULL)
{
puts("Error in function!");
return 1;
}
puts(str);
free(str);
return 0;
}
The program output is
TwinPeaks
Of course you could use standard string functions strcpy and strcat instead of the loops that can be both written even in the return statement
return result == NULL ? result : strcat( strcpy( result, s1 ), s2 );
I think that you misunderstand the meaning of malloc.
You are using malloc as if it would make a new slot in or at the end of a string. malloc(sizeX), however, reserves a new memory block with sizeX bytes somewhere in the memory (rather than at a particular position that you could determine). And the result of malloc is a pointer to a memory block, not a character.
So what you do with expression *(s + i) = (char *) malloc((strlen(s) + strlen(ct) + 1) * sizeof(char)); is actually writing a pointer value (usually something obscure when viewed as characters) as value directly into string s at the position of s's string terminating character;
For your safecat, first reserve memory for the new concatenated result string, then fill it up with your logic (I suppose this is a programming assignment and you are not allowed to use strcpy, right?
int slen = strlen(s);
int ctlen = strlen(ct);
char *result = (char *) malloc((slen + ctlen + 1) * sizeof(char));
for (int i=0; i<slen; i++)
result[i] = s[i];
for (int i=0; i < ctlen + 1 ; i++) // note "i < ctlen + 1" for considering string terminator of ct.
result[i+slen] = ct[i];
When you copy the new string to the old string you wind up putting in the null character after the initial P. What you need to do is as follows.
malloc a new buffer (ns) of the size of maxcount.
strcpy s into ns
strcpy ct into ns + strlen(s)
Note. If you are not allowed to used strcpy(), then write your own version as a function safecpy() in the a similar fashion to safecat()
return ns
Note that you would want to free ns sometime later in the program if you no longer need it.
Thank you to everyone who helped. It was a coding assignment and I was able to figure it out the next day.
The stuff I've written must have seemed to be very chaotic as I've just learned about pointers, and yes, I was not allowed to use 'strcat()' or 'strcpy()'.
My assignment for this question has already passed and I guess I misunderstood the question altogether by using numerical data types in some parts of my code. So I'm just curious as to how to solve this problem of adding/subtracting subtract two numbers represented as Strings without using numerical data types. By numerical data types, I just mean int, double, long, etc and everything needs to stay in String form.
Here is a function that performs addition of numbers in string format into an array of char, assumed to be sufficiently large and different from a and b:
char *add_numbers(char *dest, const char *a, const char *b) {
size_t lena = strlen(a);
size_t lenb = strlen(b);
size_t len = lena > lenb ? lena + 1 : lenb + 1;
char carry = 0;
dest[len] = '\0';
while (lena > 0 && lenb > 0) {
char digit = a[--lena] - '0' + b[--lenb] + carry;
carry = 0;
if (digit > '9') {
carry = 1;
digit -= 10;
}
dest[--len] = digit;
}
if (lenb > 0) {
lena = lenb;
a = b;
}
while (lena > 0) {
char digit = a[--lena] + carry;
carry = 0;
if (digit > '9') {
carry = 1;
digit -= 10;
}
dest[--len] = digit;
}
if (carry) {
dest[--len] = '1';
} else {
for (;; len++) {
dest[len - 1] = dest[len];
if (dest[len] == '\0')
break;
}
}
return dest;
}
No int, double, long, float. The number is not converted into numerical format, the operation is performed one digit at a time, in string format.
I'm guessing that you need to do arithmetic on strings digit by digit.
Like many assignments you will get in school, there is really no point in being able to do arithmetic this way, you are just supposed to learn something about the different operations and thought patterns you would need to go through.
For addition, lets take the example add("9","12") // returns "21"
In order to write this function, we will do addition the same way you learned to do it in school, first the one's digit, then the ten's and so on.
to do this, we will break call an add_digit function once for every digit.
This function will need to take the corresponding digit from both a and b as well as any carry that resulted from the addition of the previous digits.
The following code is a complete example of doing this.
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
const char * shortest(const char * a, const char * b){
if (strlen(a) <= strlen(b)){
return a;
}
return b;
}
const char * longest(const char * a, const char * b){
if (strlen(a) <= strlen(b)){
return b;
}
return a;
}
const char * add_digit(char a, char b, char carry){
/*printf("a : %c, b : %c, carry : %c\n", a, b, carry);*/
static char out[2] = {'0','0'};
int a_int = (int)(a - 48);
int b_int = (int)(b - 48);
int carry_int = (int)(carry - 48);
int sum = a_int + b_int + carry_int;
if (sum > 9){
out[0] = (sum / 10) + 48;
sum %= 10;
}
out [1] = sum + 48;
return out;
}
const char * add(const char * a, const char * b){
const char * s = shortest(a,b);
const char * l = longest(a,b);
unsigned i;
char carry = '0';
char * out = malloc(strlen(l) + 1);
for (i = strlen(l); i--;){
out[i] = ' ';
}
out[strlen(l)] = '\0';
for (i = 0; i < strlen(l); i++){
const char * digit;
if (i < strlen(s)){
digit = add_digit(s[strlen(s) - i - 1], l[strlen(l) - i - 1], carry);
} else {
digit = add_digit('0', l[strlen(l) - i - 1], carry);
}
carry = digit[0];
out[strlen(l) - i] = digit[1];
}
out[0] = carry;
return out;
}
int main(){
printf("9999 + 9 = %s\n", add("9999", "9"));
}
This code need to get an int number and convert it to array of char that present the number:
for example :
The number 324
convert to this:
like:
char newstr [6] = {'3','2','4','\0','\0','\0'};
I think that '\0' is null, right?
What is wrong with my code ?
also how can I change this to a function that get an int number and return array of char that present it?
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
void main ()
{
int value = 324;
char str [6];
char newstr [6];
int pointer, i = 0;
for(i=0; value>0; i++)
{
str[i] = value%10 + '0';
value /=10;
}
str[i] = '\0';
for(i=5; i>-1; i--)
{
if(str[i]!='\0')
{
newstr[pointer] = str[i];
pointer++;
}
}
for (i = 0; i < 6; i++)
{
printf("%d %c\n", i, newstr[i] );
}
printf ("shalom");
}
An easy way should be calling sprintf().
char newstr[6] = {0};
sprintf(newstr, "%d", value);
In your existing code, str looks lile {'4', '2', '3', '\0', SomethingRandom, SomethingRandom}. Reversing it and assign to newstr makes it {SomethingRandom, SomethingRandom, '\0', '3', '2', '4'}, which is definitely not what you want. And indeed you don't assign newstr when str[i] == '\0', which means newstr[2] == SomethingRandom.
Try the following
#include <stdio.h>
#include <stdlib.h>
char * itoa( int x )
{
const unsigned int BASE = 10;
unsigned int u = abs( x );
size_t n = 0;
unsigned int tmp = u;
char *s;
do { ++n; } while ( tmp /= BASE );
n += x < 0;
s = malloc( ( n + 1 ) * sizeof( char ) );
s[n] = '\0';
do
{
s[--n] = u % BASE + '0';
} while ( u /= BASE );
if ( x < 0 ) s[--n] = '-';
return s;
}
int main(void)
{
char *s = itoa( -1234567890 );
printf( "%s\n", s );
free( s );
return 0;
}
The output is
-1234567890
As for your question what is wrong with your code then it is entirely wrong.:)
For example the code ignores numbers that are equal to zero. Variable pointer was not initialized
int pointer, i = 0;
each loop deals with some garbage and so on.
It will be more helpful for you if you will investigate my code.
OP's code looks very close to being correct for limited usage.
Do not start with value>0 test, otherwise when value == 0, the result will be "". Be sure to limit the number of iterations to not exceed the array size.
do {
str[i] = value%10 + '0';
value /=10;
i++;
} while (value>0 && i < (6-1));
Set '\0' in a loop. #timra points out random unset elements.
do {
str[i] = '\0';
i++;
} while (i < (6-1));
OP still has 2 remaining issues which OP has yet to specify what to do:
Values greater than 99999
Values < 0
BTW: "I think that '\0' is null, right?" '\0' is the "null character". This differs from NULL, the "null pointer".
"how can I change this to a function that get an int number and return array of char that present it"
OP's code has a number of corner problems. Suggest a new approach.
Perform conversion into local array and then return a copy of it.
Calling code should eventually free() it.
#include <limits.h>
// max size needed for int. Note 10/33 just greater than log(2)
#define INTSIZE_MAX (sizeof int * CHAR_BIT * 10 / 33 + 3)
char *intoa_alloc(int x) {
char buf[INTSIZE_MAX];
char *p = &buf[sizeof buf - 1];
// Work with negative absolute value to cope with INT_MIN
// This avoids portability problems with abs(x) approach.
int x_negative = x < 0 ? x : -x;
// Form string
*p = '\0';
do {
*--p = '0' - x_negative % 10;
x_negative /= 10;
} while (x_negative);
if (x < 0) {
*--p = '-';
}
char *dest = malloc(strlen(p) + 1);
if (dest) {
strcpy(dest, p);
}
return dest;
}
In this simple way you can do that.
int main()
{
char str [6] = "324";
printf ("%c",str[1]);
return 0;
}