Issues with creating a copy of an argument in C - c

I am converting string arguments into ints I am having an issue where the first argument is not copying and converting to a string while the second argument is working just fine. I am removing the first character of the string array and printing out the rest of the string as an int.
#include <stdio.h>
#include <string.h>
#include <math.h>
int main(int argc, char *argv[])
{
char numcpy1[sizeof(argv[1])-1];
char numcpy2[sizeof(argv[2])-1];
int i, len1, len2;
int result1=0;
int result2=0;
//Access first character for base
printf("%c \n", argv[2][0]);
printf("%c \n", argv[3][0]);
//Remove first character for number1 and number 2
if(strlen(argv[2]) > 0)
{
strcpy(numcpy1, &(argv[2][1]));
}
else
{
strcpy(numcpy1, argv[2]);
}
len1 = strlen(numcpy1);
if(strlen(argv[3]) > 0)
{
strcpy(numcpy2, &(argv[3][1]));
}
else
{
strcpy(numcpy2, argv[3]);
}
len2 = strlen(numcpy2);
//Turn remaining string characters into an int
for(i=0; i<len1; i++)
{
result1 = result1 * 10 + ( numcpy1[i] - '0' );
}
for(i=0; i<len2; i++)
{
result2 = result2 * 10 + ( numcpy2[i] - '0' );
}
printf("%d \n", result1);
printf("%d \n", result2);
return 0;
}
Output:
b
b
-4844
1010
What I want:
b
b
1000
1010

The sizeof operator does not give you the length of a string, as you seem to think it does. It tell you the size of the datatype. Since argv[2] is a char *, this evaluates to the size of this pointer, most likely 4 or 8 depending on the system.
If the string in question is longer than this value, you end up writing past the end of the array. This invokes undefined behavior, which in your case manifests as an unexpected result.
If you want the length of the string, use the strlen function instead. Also, you need to add one more byte. Strings in C are null terminated, so you need space for the null byte that marks the end of the string.
char numcpy1[strlen(argv[2])];
char numcpy2[strlen(argv[3])];
Also note that we don't need to add 1 to each of these since the first character in each string isn't copied.

You need to change
char numcpy1[sizeof(argv[1])-1];
to
char numcpy1[strlen(argv[1]) + 1];
Ditto for numcpy2

I think instead of copying the numbers you could work more easily with pointers. Thereby, you don't have to think about memory allocation and copying the values just for the sake of converting them into an integer value:
const char *numcpy1 = argv[2][0]=='\0' ? argv[2] : argv[2]+1;
...

Related

Add zero padding to string in c?

The concept is very similar to this Add zero-padding to a string but it's a question from c# NOT C.
While you can add a zero padding in printf like this printf("%4d", number)
How can I have a zero padding to a string? ex:
char *file_frame = "shots";
strcat(file_frame, "%3d", number); // It's my attempt to solve it. I know it's wrong
so that I would get shots000 from file_frame
You need to use sprintf
sprintf(file_frame, "%04d", 34);
The 0 indicates what you are padding with and the 4 shows the length of the integer number.
Also you should be using mutable array as below.
char *file_frame = "shots"; --> char file_frame[100] = "shots";
First you need some space to store the string. Then you "print" into this string:
#include <stdio.h>
#include <stdlib.h>
int main(void) {
char file_name[8 + 1]; // "shots###" is 8 characters, plus 1 for end-of-string marker '\0'
int number = 23;
sprintf(file_name, "shots%03d", number);
printf("\"%s\"\n", file_name);
return EXIT_SUCCESS;
}
You can combine literal parts with formatting parts in any *printf() function.
Well, this is the workaround I did: -
char output[9];
char buffer[9];
itoa(num, output, 2);
int i=0;
for (i=0; i<(8-strlen(output));i++) {
buffer[i]='0';
}
for(int j=0;j<strlen(output);j++){
buffer[i] = output[j];
i++;
}
Input:-
num = 10
Output: -
buffer = 00001010

Parse string to number in C

I tried to write a function to convert a string to an int:
int convert(char *str, int *n){
int i;
if (str == NULL) return 0;
for (i = 0; i < strlen(str); i++)
if ((isdigit(*(str+i))) == 0) return 0;
*n = *str;
return 1;
}
So what's wrong with my code?
*n = *str means:
Set the 4 bytes of memory that n points to, to the 1 byte of memory that str points to. This is perfectly fine but it's probably not your intention.
Why are you trying to convert a char* to an int* in the first place? If you literally just need to do a conversion and make the compiler happy, you can just do int *foo = (int*)bar where bar is the char*.
Sorry, I don't have the reputation to make this a comment.
The function definitely does not perform as intended.
Here are some issues:
you should include <ctype.h> for isdigit() to be properly defined.
isdigit(*(str+i)) has undefined behavior if str contains negative char values. You should cast the argument:
isdigit((unsigned char)str[i])
the function returns 0 if there is any non digit character in the string. What about "-1" and "+2"? atoi and strtol are more lenient with non digit characters, they skip initial white space, process an optional sign and subsequent digits, stopping at the first non digit.
the test for (i = 0; i < strlen(str); i++) is very inefficient: strlen may be invoked for each character in the string, with O(N2) time complexity. Use this instead:
for (i = 0; str[i] != '\0'; i++)
*n = *str does not convert the number represented by the digits in str, it merely stores the value of the first character into n, for example '0' will convert to 48 on ASCII systems. You should instead process every digit in the string, multiplying the value converted so far by 10 and adding the value represented by the digit with str[i] - '0'.
Here is a corrected version with your restrictive semantics:
int convert(const char *str, int *n) {
int value = 0;
if (str == NULL)
return 0;
while (*str) {
if (isdigit((unsigned char)*str)) {
value = value * 10 + *str++ - '0';
} else {
return 0;
}
}
*n = value;
return 1;
}
conversion of char* pointer to int*
#include
main()
{
char c ,*cc;
int i, *ii;
float f,*ff;
c = 'A'; /* ascii value of A gets
stored in c */
i=25;
f=3.14;
cc =&c;
ii=&i;
ff=&f;
printf("\n Address contained
in cc =%u",cc);
printf("\n Address contained
in ii =%u",ii);
printf(:\n Address contained
in ff=%u",ff);
printf(\n value of c= %c",
*cc);
printf(\n value of i=%d",
**ii);
printf(\n value of f=%f",
**ff);
}

How to print only some characters in C?

I have an array:
char arr[]="This is the string";
For instance, if I want to print only first 5 characters of that string, I have tried the following:
printf("%-5s",arr);
But it is printing whole string. Why?
You can use %.*s, it takes size of intended bytes to be printed and pointer to char as arguments when using with printf. For example,
// It prints This
printf("%.*s", 4, arr);
But it is printing whole string. Why?
You are using %-5s meaning the - left-justifies your text in that field.
En passant, the output cannot be achieved by using the accepted answer as simply as the code snippet, even if it may be seemed derisively.
int i;
char arr[]="This is the string";
for (i = 1; i < sizeof(arr); ++i) {
printf("%.*s\n", i, arr);
}
Output:
T
Th
Thi
This
This
This i
This is
This is
This is t
This is th
This is the
This is the
This is the s
This is the st
This is the str
This is the stri
This is the strin
This is the string
- is a printf formater for justification, not precision.
What you want is the . formater which is used for precision :
printf("%.5s", arr);
This will print the first 5 elements of arr.
If you want to learn more about printf formaters, take a look at this link.
for example substring extraction function (extracts substring to the buff)
char *strpart(char *str, char *buff, int start, int end)
{
int len = str != NULL ? strlen(str) : -1 ;
char *ptr = buff;
if (start > end || end > len - 1 || len == -1 || buff == NULL) return NULL;
for (int index = start; index <= end; index++)
{
*ptr++ = *(str + index);
}
*ptr = '\0';
return buff;
}
You can do it quite simply in a number of ways. With a loop, looping the number of times desired, picking off chars each time, you can walk a pointer down the string an temporary nul-terminate after the 5th character, or you can simply use strncpy to copy 5 chars to a buffer and print that. (that is probably the simplest), e.g.
#include <stdio.h>
#include <string.h>
int main (void)
{
char arr[]="This is the string",
buf[sizeof arr] = ""; /* note: nul-termination via initialization */
strncpy (buf, arr, 5);
printf ("'%s'\n", buf);
return 0;
}
Example Use/Output
$ ./bin/strncpy
'This '
Look things over and let me know if you have any questions.

C program calling a string to int function, I am unable to convert the input

I would like to convert a string to an int and calling the function from main. Where the first character is a letter declaring the base of the number and the rest of the characters in the string are the number. I am able to get the function to work separately, but when using the main function to call it will not print out the correct values.
Example of user input using binary:
b1000
b1010
result should be:
b
b
1000
1010
Here is the code:
#include <stdio.h>
#include <string.h>
#include <math.h>
int str_to_int(inputbase) {
char num1[50];
num1[50] = inputbase;
char numcpy1[sizeof(num1) - 1];
int i, len1;
int result1 = 0;
//printf("String: ");
//gets(num1);
//Access first character for base
printf("%c \n", num1[0]);
//Remove first character for number1 and number 2
if (strlen(num1) > 0) {
strcpy(numcpy1, &(num1[1]));
} else {
strcpy(numcpy1, num1);
}
len1 = strlen(numcpy1);
//Turn remaining string characters into an int
for (i = 0; i < len1; i++) {
result1 = result1 * 10 + ( numcpy1[i] - '0' );
}
printf("%d \n", result1);
return result1;
}
int main() {
char *number1[50], *number2[50];
int one, two;
printf("\nAsk numbers: \n");
gets(number1);
gets(number2);
one = str_to_int(number1);
two = str_to_int(number2);
printf("\nVerifying...\n");
printf("%d\n", one);
printf("%d\n", two);
return 0;
}
I suppose your code cannot be compiled because some errors.
The first one is in the line
int str_to_int(inputbase)
where inputbase are defined without type.
If this changed to
int str_to_int(char * inputbase)
the next point for improvement is in line
num1[50] = inputbase;
assignement like that has set of errors:
num1[50] means access to 51th item, but there is only 50 items indexed from 0 to 49
statement num1[0] = inputbase; (as well as with any other correct index) is wrong because of difference in types: num1[0] is char, but inputbase is pointer
num1 = inputbase; will be also wrong (for copying string = cannot be used in C, so consider making loop or using standard library function strncpy)
And since this is only the beginning of problems, I suggest starting from decimal input using some standard function for conversion char* string to int (e.g. atoi, or sscanf), then after you check the program and find it correct if it is required you can avoid using standard conversion and write your own str_to_int
The prototype for your function str_to_int() should specify the type of intputbase. You are passing a string and there is no reason for str_to_int to modify this string, so the type should be const char *inputbase.
Furthermore, you do not need a local copy for the string, just access the first character to determine the base and parse the remaining digits accordingly:
#include <stdlib.h>
int str_to_int(const char *inputbase) {
const char *p = inputbase;
int base = 10; // default to decimal
if (*p == 'b') { // binary
p++;
base = 2;
} else
if (*p == 'o') { // octal
p++;
base = 8;
} else
if (*p == 'h') { // hexadecimal
p++;
base = 16;
}
return strtol(p, NULL, base);
}

C convert section of char array to double

I want to convert a section of a char array to a double. For example I have:
char in_string[] = "4014.84954";
Say I want to convert the first 40 to a double with value 40.0. My code so far:
#include <stdio.h>
#include <stdlib.h>
int main(int arg) {
char in_string[] = "4014.84954";
int i = 0;
for(i = 0; i <= sizeof(in_string); i++) {
printf("%c\n", in_string[i]);
printf("%f\n", atof(&in_string[i]));
}
}
In each loop atof it converts the char array from the starting pointer I supply all the way to the end of the array. The output is:
4
4014.849540
0
14.849540
1
14.849540
4
4.849540
.
0.849540
8
84954.000000 etc...
How can I convert just a portion of a char array to a double? This must by modular because my real input_string is much more complicated, but I will ensure that the char is a number 0-9.
The following should work assuming:
I will ensure that the char is a number 0-9.
double toDouble(const char* s, int start, int stop) {
unsigned long long int m = 1;
double ret = 0;
for (int i = stop; i >= start; i--) {
ret += (s[i] - '0') * m;
m *= 10;
}
return ret;
}
For example for the string 23487 the function will do this calculations:
ret = 0
ret += 7 * 1
ret += 8 * 10
ret += 4 * 100
ret += 3 * 1000
ret += 2 * 10000
ret = 23487
You can copy the desired amount of the string you want to another char array, null terminate it, and then convert it to a double. EG, if you want 2 digits, copy the 2 digits you want into a char array of length 3, ensuring the 3rd character is the null terminator.
Or if you don't want to make another char array, you can back up the (n+1)th char of the char array, replace it with a null terminator (ie 0x00), call atof, and then replace the null terminator with the backed up value. This will make atof stop parsing where you placed your null terminator.
Just use sscanf. Use the format "ld" and check for return value is one.
What about that, insert NULL at the right position and then revert it back to the original letter? This means you will manipulate the char array but you will revert it back to the original at the end.
You can create a function that will make the work in a temporary string (on the stack) and return the resulting double:
double atofn (char *src, int n) {
char tmp[50]; // big enough to fit any double
strncpy (tmp, src, n);
tmp[n] = 0;
return atof(tmp);
}
How much simpler could it get than sscanf?
#include <assert.h>
#include <stdio.h>
int main(void) {
double foo;
assert(sscanf("4014.84954", "%02lf", &foo) == 1);
printf("Processed the first two bytes of input and got: %lf\n", foo);
assert(sscanf("4014.84954" + 2, "%05lf", &foo) == 1);
printf("Processed the next five bytes of input and got: %lf\n", foo);
assert(sscanf("4014.84954" + 7, "%lf", &foo) == 1);
printf("Processed the rest of the input and got: %lf\n", foo);
return 0;
}

Resources