I am learning how to delimate char arrays and I need to do an operation where I split a number and string into different variables and print them out. I believe I am close but when printing out what should be my number I get crazy numbers. Is this the address to the int? Any advice is greatly appreciated! My code and input/output:
#include <stdio.h>
int main() {
setbuf(stdout, NULL);
char name[10];
printf("Enter in this format, integer:name\n");
fgets(name, 10, stdin); //my input was 2:brandon
char *n = strtok(name, ":");
int num = (int)n;
char * order = strtok(NULL, ":");
printf("%d,%s", num,order); //my output was 7846332,brandon
return (0);
}
This line is incorrect:
int num = (int)n;
Is this the address to the int?
No, it is an address of the character buffer at the position where the character representation of your integer is stored, re-interpreted as an int (i.e. it may be a truncated address, making it pretty much a meaningless number).
You can convert it to int either by parsing the value, or using atoi:
int num = atoi(n);
Demo.
If you give e.g. "123:foobar" as input, the pointer n points to the string "123". When you cast the pointer to an integer, the value of the integer is the value of the variable n which is the address of where in memory the string returned by strtok is located.
If you want to convert a string containing a number to an actual number, you should use e.g. the strtol function:
int num = strtol(n, NULL, 10);
Related
I am trying to convert a number from base b to base 10 using the function base_b_to_10 as below:
long int base_b_to_10(char* B, long int base) //take in the number as string returns it converted to base 10 as long int
{
long int N; //base 10 number:
N = strtol(B, NULL, base); //
return(N);
}
In the main program, the user will input the base of the input number and the input number itself.
The length and the size of the string is unknown and is up to the user to define
This is a simplified version of a big program I am trying to build in which the size of the string B is dynamically allocated in another function so I cannot do something like:
char B[100];
How to solve this? the compiler is returning nothing.
Input string (here: test) can be of any reasonable size. Anyway, there might be some limitations, see: Strtol() and atol() do not convert strings larger than 9 digits
Output string is a pointer (here: *str) to position within input string (here: test). According to this, the size of the string to which str points does not matter. (Note: In this example, str is only valid as long as test is valid).
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
long int base_b_to_10(char* B, long int base, char **ret_str)
{
long int N;
N = strtol(B, ret_str, base);
return N;
}
int main()
{
long int val;
char *str;
char test[50] = "43724325HelloWorld";
val = base_b_to_10(test, 10, &str);
printf("val = %ld\n", val);
printf("str = %s\n", str);
return 1;
}
Notes: I adapted your example just to be working (not improving or simplifying anything). It is probably clear that you could also directly use strtol function in the main routine. Moreover, it does not matter, how the input string was allocated (fixed size or dynamic size) - just needs to be allocated and needs to end by \0 (as usual).
If cross platforming is not an issue, and assuming you are running on a linux system, you can make use of asprintf().
It basically formats your string and allocates the memory for you (remember to free it afterwards).
This is not part of the standard library so it has its limitations.
Another approach is to use snprintf() to preddict the size of the output buffer then and use malloc()
#include <stdio.h>
int main ()
{
int cx = snprintf ( NULL, 0, "18 characters long" );
printf("%d", cx);
return 0;
}
// OUTPUT:
// 18
Ok so I solved this problem by first using a buffer string with size 50 (pretty sufficient), than I used the strlen() function to determine the size of the string given by the user, and lastly I allocate this number to the string I will be using for the conversion:
char *str, buffer[50];
printf("enter the input value: ");
gets(buffer);
int i;
i = strlen(buffer);
str = (char*)malloc(i*sizeof(char));
strcpy(str, buffer);
fflush(stdin);
N = base_b_to_10(str, base_in);
During an interview, I was asked to implement a solution for following problem in C programming language:
Given an input string with a fixed pattern of contents separated by a delimiter, I need to extract each specific content.
Pattern of input string: "starting_message|integer_value_1|integer_value_2|character_code|ending_message"
Expected output:
Starting message: starting_message
Value 1 : integer_value_1
Value 2 : integer_value_2
Char code : character_code
Ending message : ending_message
Example input: "HelloWorld|35|45|C|ByeWorld"
Example output:
Starting message: HelloWorld
Value 1 : 35
Value 2 : 45
Char code : C
Ending message : ByeWorld
I implemented the following code:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
/*
Loop through the input string until termination.
Figure out the position of delimiters first. It will help in parsing later.
For string, count the number of chars and use memcpy for that number of elements.
To parse char to int, try atoi.
*/
void parse(const char* input, char* starting_message, int* value1, int* value2, char* char_code, char* ending_message)
{
int ctr = 0, pos_ctr=0;
int delim_pos[4]; /* To store the location of delimiters aka '|' */
char* value1_str = (char*) malloc(10);
char* value2_str = (char*) malloc(10);
while(input[ctr]!= '\0')
{
if(input[ctr] == '|')
{
if(pos_ctr < 4)
{
delim_pos[pos_ctr] = ctr;
pos_ctr++;
}
}
ctr++;
}
memcpy(starting_message,input,(delim_pos[0])); /* starting_message is contained in input string in between input[0] & input[delim_pos[0]]*/
starting_message[delim_pos[0]+1] = '\0';
memcpy(value1_str, input,(delim_pos[1]-delim_pos[0])); /* value1 is contained in input string in between input[delim_pos[0]] & input[delim_pos[1]]*/
value1_str[(delim_pos[1]-delim_pos[0] + 1)] = '\0';
*value1 = atoi(value1_str);
memcpy(value2_str, input,(delim_pos[2]-delim_pos[1])); /* value2 is contained in input string in between input[delim_pos[1]] & input[delim_pos[2]]*/
value1_str[(delim_pos[2]-delim_pos[1] + 1)] = '\0';
*value2 = atoi(value2_str);
*char_code = input[(delim_pos[2]+1)]; /* char_code is element next to input[delim_pos[2]]*/
memcpy(ending_message, input, (delim_pos[3]-ctr-1)); /* ending_message is contained in input string in between input[delim_pos[3]] & null termination char*/
ending_message[delim_pos[3]-ctr] = '\0';
}
int main() {
const char* input = "HelloWorld|35|45|C|ByeWorld";
char* starting_message = (char*) malloc(30);
char* ending_message = (char*) malloc(30);
int value1, value2;
char char_code;
parse(input, starting_message, &value1, &value2, &char_code, ending_message);
printf(" Input string: %s\n",input);
printf("Starting message : %s\n", starting_message);
printf("Value 1 : %d\n", value1);
printf("Value 2 : %d\n", value2);
printf("Character code : %c\n", char_code);
printf("Ending message: %s\n", ending_message);
return 0;
}
I was able to compile but on the output screen, I encountered a segmentation fault with no output.
Where did I go wrong and how to fix it?
Your segmentation fault occurs here:
memcpy(ending_message, input, (delim_pos[3]-ctr-1));
Typical causes for segmentation faults are null or garbage pointers, but here, it's something else: You have miscalculated the number of bytes to copy, because you got the subtraction the wrong way round. It should be
ctr + 1 - delim_pos[3]
because, if everything went well, str is past delim_pos[3]. (But you don't check that pos_ctr == 4, so you don't know whether everything went well.)
The third parameter to memcpy is of the unsigned integer type size_t. By mixing up the subtraction, you got a small negative int value, which will be a huge positive value when converted to an unsigned value, which certainly leads to out-of-bounds access.
For starters the function does not report whether parsing of the input string was successful.
The function has too many parameters. Instead of this list of parameters
char* starting_message, int* value1, int* value2, char* char_code, char* ending_message
you could pass an object of a structure type. For example the function declaration could be
int parse( const char *input, struct Fields *fields );
These memory allocations
char* value1_str = (char*) malloc(10);
char* value2_str = (char*) malloc(10)
are redundant and moreover due to these allocations the function produces memory leaks.
Instead of the function atoi you should use the function strtol.
Instead of this while loop
while(input[ctr]!= '\0')
you could use a loop within which there is called the function strchr.
In this assignment
starting_message[delim_pos[0]+1] = '\0';
the character at the position delim_pos[0] can have indeterminate value. Instead of the statement above you have to write
starting_message[delim_pos[0]] = '\0';
In these statements
memcpy(value1_str, input,(delim_pos[1]-delim_pos[0]));
memcpy(value2_str, input,(delim_pos[2]-delim_pos[1]));
memcpy(ending_message, input, (delim_pos[3]-ctr-1));
you are copying characters beginning from the start of the string input that does not make a sense. Moreover this expression delim_pos[3]-ctr-1 will yield a negative value.
This statement
ending_message[delim_pos[3]-ctr] = '\0';
invokes undefined behavior because the value of the expression delim_pos[3]-ctr is negative. ctr stores the length of the input string.
Thus the function has undefined behavior and does not make a great sense.:)
#include<stdio.h>
#include<conio.h>
#include<string.h>
int main() { {
char sir[3000];
int i;
int suma = 0;
int lungime;
scanf("%s", sir);
lungime = strlen(sir);
char x;
char *pX;
x = sir[2];
pX = &x;
suma = atoi(pX);
return 0;
}
I am doing the adventOfCode, Day1.
My problem is that I cannot pick certain digits from the string, using atoi.
From what I read, atoi needs a pointer as argument.
if i read some big string like "111555434536563673673567367...."
with a length between 2000 - 3000
I can't understand why when I print "suma", instead of printing the certain digit from my string, it prints some huge integer, like 83506.
From what I read, atoi needs a pointer as argument.
Needing a pointer is only part of the deal. The other part is that the pointer needs to point to a null-terminated string representing an integer.
Moreover, x = sir[2]; pX = &x is not how you get a pointer to the second element of sir[] array: x is a copy of the third digit (arrays are zero-based), and pX is a pointer to that copy.
If you want to get a numeric value of a single digit, subtract '0' from it (note single quotes around zero):
int thirdDigitVal = sir[2] - '0';
If you need to do it with atoi, copy the digit into a null-terminated string:
char copy[2] = {0};
copy[0] = sir[2];
int thirdDigitVal = atoi(copy);
so i've been writing a program that convert a decimal number to it's boolean representation but every time i compile the return value which is a string show additional characters like pā here is the program
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void main (void)
{
signed char str[256];
int dec,rest;
int i = -1;
int j;
printf ("write a decimal number : ");
scanf ("%d",&dec);
do
{
rest = dec % 2;
dec/= 2;
for (j=i;j>-1;--j)
str[j+1]=str[j];
str[0]=rest+48;
++i;
} while (dec!=0);
printf ("the binary representation of this number is %s",str);
}
the output :
write a decimal number : 156
the binary representation of this number is 10011100pā
i don't know if im missing something but i will be grateful if you guys help me
In C and C++, strings are null-terminated, this means that every valid string must end with a character with code 0. This character tells every function that is dealing with this string that it is in fact over.
In your program you create a string, signed char str[256]; and it is initially filled with random data; this means that you reserved space for 256 characters and they are all garbage, but the system does not know they are invalid. Try printing this string and see what happens.
In order to actually tell the system that your string is over after say, 8 characters, the 9th character hast to be the NUL character, or simply 0. In your code you can do it in two ways:
after the loop, assign str[i] = 0, or (even simpler)
initialize the string as signed char str[256]={0};, whiche creates the storage and fills it with nulls; after writing to the string you can be sure that the character after the last one you've written will be a NUL.
At the end of your do {} while () loop, you need to set the character after the last character in your string to 0. This is the array index of the last character you want (i) plus one. This lets printf know where your string ends. (Otherwise, how could it know?)
initialize the str variable to NUL.
void main (void)
{
signed char str[256];
int dec,rest;
int i = -1;
int j;
memset( str, '\0', sizeof(str) );
printf ("write a decimal number : ");
scanf ("%d",&dec);
do
{
rest = dec % 2;
dec/= 2;
for (j=i;j>-1;--j)
str[j+1]=str[j];
str[0]=rest+48;
++i;
} while (dec!=0);
printf ("the binary representation of this number is %s",str);
}
EXAMPLE:
If I have this string/array: "123 45 6" (The numbers are separated by at least one space), how can I separate the numbers so I can use the numbers 123,45 and 6 separately?
I have know idea how to do it.
Thanks for helping!
Try strtol() (prototype in <stdlib.h>)
char data[] = "123 45 6";
char *p = data;
while (*p) {
long k = strtol(p, &p, 10);
/* add error checking */
printf("%ld\n", k);
}
Though I find the strtol-approach of png the most elegant way, let me also propose an approach utilising the "%n"-feature of scanf. This feature returns the number of characters scanned so far and can be used for pointing to the next portion to read in:
int main() {
const char *data = "123 45 6 ";
while (data && *data) {
int value=0;
int index=0;
if (sscanf(data,"%d%n",&value,&index) != 1)
break;
printf("%d\n", value);
data+=index;
}
}
You have to create a function which will split your string in a double array of strings, using spaces as a delimiter.
The prototype of this function would be for example :
char **StrSplit(char *str, char c);
Then you would be able to call it in your code with str as the string you want to take the numbers from, and c as the space character (or any character used as a delimiter).
It would return a double array of strings containing in each entry a string for each number.
Then you would be able to convert each entry (containing a string of numbers) as an integer using the function atoi on it.