String manipulation in C is the bane of my existence, I have tried to understand how to manipulate char arrays and fall short of grasping it every time. I simply want to do this in C.
Method1 passes ["1298","9"]
Method2 receives and converts them both to ints
int method1(){
char *values[2];
int i = 1298;
int j = 9;
//sprintf(values,"%d" "%d",i,j);
sprintf(&values[0],"%d" ,i);
sprintf(&values[1],"%d" ,j);
method2(values,2);
}
int method2(char *strings, int num_values){
int i, j;
char buffer[256];
sscanf(buffer, "%d" "%d", &i, &j);
printf("i: %d, j: %d\n",i,j);
return 0;
}
The result of this is 1 and 9; but i want 1298 and 9
Please even after providing an answer, can you explain why it is the way it is?
char *values[2];
The above line is parsed as char *(values[2]);, i.e., [] take precedence over *. This means that values is an array with 2 elements. The type of the elements is char *. So, values[0] and values[1] are of type char *. Since you haven't initialized the array elements, the two items in the array have unknown, random values.
//sprintf(values,"%d" "%d",i,j);
Although you have commented this out, it seems like you were trying to store the string representation of i and j into values using one sprintf call. As you probably found out, this is impossible.
sprintf(&values[0],"%d" ,i);
Here, you are calling sprintf to store the string representation of i into the memory location pointed to by values[0]. But as noted above, values[0] is not pointing anywhere useful, since you haven't initialized it. This is bad.
sprintf(&values[1],"%d" ,j);
Same as above.
method2(values, 2);
Here, you are calling method2, but you haven't declared the signature of method2. As it turns out, method2 takes a char * and an int. You are passing values and 2. values is an array of char *, which gets converted to a pointer in this context, so method2 should take a char ** and an int.
int method2(char *strings, int num_values){
This should be: int method2(char **strings, int num_values) {
int i, j;
char buffer[256];
sscanf(buffer, "%d" "%d", &i, &j);
I am not sure what you are trying to do here. You are ignoring strings, but instead using a buffer variable. buffer is uninitialized, so trying to interpret the data in it as two integers is pointless.
I am assuming you are writing this program to understand strings, pointers, and functions. As such, there is no single correct way to do what you are trying to do. But here is one approach:
#include <stdio.h>
/* Define method2 before method1, so that its definition is visible
in method1 */
/* Assume that method2 will be called with one char * containing two integer
values. I also changed the return type to void since you weren't really
using the int return value. Same for method1. */
void method2(const char *strings)
{
int i, j;
sscanf(strings, "%d %d", &i, &j);
printf("i: %d, j: %d\n",i,j);
}
void method1(void)
{
/* Changed values to a char array that has enough space */
char values[256];
int i = 1298;
int j = 9;
sprintf(values, "%d %d", i, j);
method2(values);
}
int main(void)
{
method1();
return 0;
}
The above outputs:
i: 1298, j: 9
There are a lot of moving parts in your program. I recommend that you learn the basics about pointers, arrays etc., in C, before passing them around in functions.
The result of your program is called UNDEFINED BEHAVIOR. You MUST use compiler warnings if you are learning.
Your code has many issues, you should READ about strings in c instead of trying stuff just to see if they work.
You are using sprintf() wrong, you should pass a pointer to char as the first parameter, that points to valid data. You are passing uninitialized pointers instead which leads to undefined behavior.
Function method1() (please note, that methods are for classes or objects, in c there are no methods, just functions) is also not passing anything anywhere. The array of pointer values is local to the function and is not accessible from outside the function. To pass something to a function you should do it through the parameters instead and it would be the other way around since you can't call main() from a c program because it is undefined behavior.
You are using sscanf() where you apparently what fscanf() or just scanf().
If you want to read input from the user use
if (scanf("%d %d", &i, &j) == 2)
printf("i: %d, j: %d\n", i, j);
else
printf("Invalid input\n");
you can substitute scanf() with fscanf(stdin, ... or another FILE * object to read from a file.
In your code, your program is expecting buffer to contain a string (a sequence of bytes terminated with a '\0'). You are passing an uninitialized array instead which invokes undefined behavior.
If you want to test how sscanf() works, do this
char buffer[] = "1 2";
if (sscanf(buffer, "%d %d", &i, &j) ...
the rest is the same.
I would say, that you want this
int
main(void)
{
char buffer[256];
int i;
int j;
sprintf(buffer, "%d %d", 1289, 9); // - This is not necessay, but for illustration
// - This is also, unsafe as it could cause
// a buffer overflow.
if (sscanf(buffer, "%d %d", &i, &j) == 2) // Would be surprised if this is false,
printf("values: %d %d\n", i, j); // but you MUST always check to make
else // sure, because this kind of situation
printf("invalid input?\n"); // is very unusual in real code.
}
I hope you can see, why your code is SO wrong. You can also move the part you want to the function. But it should be the right part.
Here's something I wrote up quickly; you can pass an array of strings to this function along with it's length and it will dynamically allocate an array of integers with their converted values.
The pitfall here is that with strtol: if it fails to convert one of the strings it will default to 0. So if an element in your array of strings happens to contain some non-numeric characters you may not get what you expect; and an error won't be reported as you'd have to also confirm that the string itself wasn't 0.
#include <stdlib.h>
#include <stdio.h>
int *convert_to_int_array(const char **strings, size_t length) {
int *numbers = malloc(length * sizeof(int));
size_t i = 0;
if(numbers == NULL)
return NULL;
for(i = 0; i < length; i++) {
numbers[i] = strtol(strings[i], NULL, 10);
}
return numbers;
}
int main(int argc, char **argv) {
const char *strings[2];
strings[0] = "100";
strings[1] = "50";
int *numbers;
size_t length = 2, i;
numbers = convert_to_int_array(strings, length);
if(numbers == NULL) {
fprintf(stderr, "failed to initialize numbers\n");
}
for(i = 0; i < length; i++) {
printf("%d\n", numbers[i]);
}
return EXIT_SUCCESS;
}
Try this:
char values[10];
int i = 1298;
int j = 9;
sprintf(values,"%d %d",i,j);
Related
In what way is the following code faulty or undefined behaviour?
I suggested this as a possibility to create an array of strings, if string number and size are unknown beforehand, and after a short discussion, it was suggested that I open a new question.
The following code produced the expected results when I compiled it with gcc, but that can happen in spite of undefined behaviour (it's undefined after all).
So, what is the mistake?
int n, i;
printf("How many strings? ");
scanf("%d", &n);
char *words[n];
for (i = 0; i < n; ++i) {
printf("Input %d. string: ", i + 1);
scanf("%s", &words[i]);
}
for (i = 0; i < n; ++i) {
printf("%s\n", &words[i]);
}
Edit:
I feel stupid now for missing this, I guess getting the correct answer back just made me miss my error. But that others may learn from my mistake:
I guess I got completely wrong what the & operator does. I thought it would give me where words points to, but of course it does the exact opposite. See the answers.
scanf("%s", &words[i]); and printf("%s\n", &words[i]); invokes *undefined behavior because data having wrong type are passed.
In both of scanf() and printf(), %s requires char* pointing at valid buffer but what is passed are char**.
Also don't forget to allocate buffer to store strings before reading.
Try this:
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int n, i;
printf("How many strings? ");
scanf("%d", &n);
char *words[n];
for (i = 0; i < n; ++i) {
printf("Input %d. string: ", i + 1);
words[i] = malloc(1024001); /* allocate enough buffer */
if (words[i] == NULL) {
perror("malloc");
return 1;
}
scanf("%1024000s", words[i]); /* limit length to read to avoid buffer overrun */
}
for (i = 0; i < n; ++i) {
printf("%s\n", words[i]);
}
for (i = 0; i < n; ++i) {
free(words[i]); /* clean what is allocated */
}
return 0;
}
char *words[n];
creates an array of uninitialized pointers
scanf("%s", foo);
writes values to the position foo is pointing to
it is not specified where the pointers of words are pointing to so they could point anywhere which could result in a segfault
next words is a char**
words[i] is a char *
&words[i] is a char **
%s expects a char* so it's again undefined behavior what happens
so you first have to initialize your words arrays using for example malloc and then write the values to words[i]
This:
char *word;
is a pointer, Before it is used as a container for say a string, it needs to point to memory sufficient for the string.
for example, this will work
word = malloc(80*sizeof(*word));
if(word)
{//success, continue
Similar to above, this:
char *word[n];
extension is an an array of n pointers. Before any of the pointers can be used as a container for say some strings, each needs to point to its own memory location. Assuming the value n has been scanned in, this will work:
for(int i=0;i<n;i++)
{
word[i] = malloc(80*sizeof(*word[i]));//80 for illustration
if(!word[i])
{//handle error...
Once the memory is allocated, the strings can be populated.
However, to ensure user input does not overflow the buffer defined by each instance of word, use a width specifier in the format string:
Change:
scanf("%s", &words[i]);
To:
scanf("%79s", words[i]);//note & is not needed as the symbol for a char array serves as the address
// ^^ ^
#include<stdio.h>
char bin(int);
int main()
{
setbuf(stdout,NULL);
int num;
char res[50];
printf("Enter the number: ");
scanf ("%d",&num);
res=bin(num);
printf("%s",res);
return 0;
}
char bin(int num)
{
char str[50];
int i,val;
for(i=0;num>=0;i++)
{
val=num%2;
str[i]=val;
num=num/2;
}
return str;
}
I really cant understand the error in the usage of strings... to convert the decimal to binary. Whats the conceptual error Im not following?
char is a single character, so char bin(int) will not be able to return a string (i.e. a null-terminated array of characters). And you cannot "return" an an array of characters, because C does not allow to return any array as function result. You can just pass/return pointers to the begin of such arrays.
So I'd suggest to change the interface of bin to reicieve the result buffer as parameter. Don't forget to "close" the string, i.e. to write the string termination character after the last "actual" character:
void bin(int num, char* resultBuffer) {
...
resultBuffer[i] = '\0';
}
In main, you call it then like
bin(num, res);
Returning str amounts to returning a local variable, you can't do it, what you can do is to return a pointer to a previously allocated memory block that works as an array (as an alternative to the oher answer, which is a good solution).
To do this you can declare str as a pointer, allocate memory for it and return it, making sure the variable to which the value is assigned is also a pointer, all the rest can remain the same.
There are, however, problems with the bin function.
Consider the statement:
str[i] = val;
This will not work as expected you are assigning the int result of the operation, which will be 1 or 0, you need to convert this value to the respective character.
The loop for (i = 0; num >= 0; i++) is an infinite loop because num will never be negative, unless you provide it a negative number in which case it will break in the first iteration, that is to say this code only works with positive integers. You need > instead of >=.
Finally you need to null terminate the string when the conversion is complete.
Corrected code (Online):
#include <stdio.h>
#include <stdlib.h>
char *bin(int); //return pointer
int main() {
setbuf(stdout, NULL);
int num;
char *res; //use pointer to receive string assignment
printf("Enter the number: ");
scanf("%d", &num);
res = bin(num);
printf("%s", res);
return 0;
}
char *bin(int num) {
char *str = malloc(50); // allocate memory
int i, val;
for (i = 0; num > 0; i++) { // replacing >= with >
val = num % 2;
str[i] = val + '0'; // convert to character
num = num / 2;
}
str[i] = '\0'; //null terminate the string
return str;
}
Note that you should also check for the inputed value, if it is larger than what an int variable can hold it will result in undefined behavior.
I have written this script, and the aim of it is to get in input a phrase and to print just the first word (the one before the first space). I cannot understand why, when I execute it, I get a bunch of numbers in the output.
#include <stdio.h>
#include <stdlib.h>
#define MAX 30
/*
Prende in input una frase e stampa la prima parola
*/
char *fw();
int main () {
int j,i;
char parola[MAX], *p;
printf ("Inserisci una stringa: ");
fgets(parola, MAX, stdin);
p = fw(&parola, &i);
for (j=0; j < i; j++){
printf("%d", p[j]);
}
return 0;
}
char *fw(char *parola, int *puntatoreI) {
int i;
char *p;
for (i=0; parola[i]!=' '; i++)
;
p = (char *)malloc((i+1)*sizeof(char));
for (i=0; parola[i]!=' '; i++){
p[i] = parola[i];
}
p[i+1] = '\0';
puntatoreI = &i;
return p;
}
puntatoreI = &i;
Is assigning a pointer puntatoreI to point to variable i. You don't want to do that. You want to modify variable i inside main, that is where the pointer puntatoreI points to. You want:
*puntatoreI = i;
You are allocating (i+1) characters for p. Yet you are assigning to p[i+1] = '\0'; is accessing 1-byte out of bounds. Just p[i] = '\0';. i is the last index in an array of i+1 elements.
Using empty braces in function declaration char *fw(); is very old. To make sure your code is ok, just repeat the function declaration from the definition char *fw(char *parola, int *puntatoreI);.
The type of &parola is char (*)[30] - it's a pointer to an array of 30 characters. Yet, the fw function takes char * - a pointer to char. Just pass parola as in p = fw(parola, &i);.
And finally, to your question:
why when I execute it I get a bunch of numbers in output.
You get a "bunch of numbers" on the output, because you print them with printf("%d",p[j]);. %d is a printf format specifier used to print numbers in base 10. To print characters as they are, use %c format specifier. But because p should point to a zero-terminated array of characters (to a string), you could do just printf("%s", p); instead of the whole loop.
The program stops working.
Even if I put only one int.
I tried many different ways but can't figure out what is wrong.
I am trying to take input of integers separated by space.
There can be any no of integers.
#include<stdio.h>
#include<stdlib.h>
int main(void) {
int i,j=0;
int b[100];
char a[100];
fgets(a,100,stdin);
for(i=0;i<strlen(a);i++)
{
b[i] = atoi(a[j]);
j=j+2;
}
for(i=0;i<strlen(b);i++)
{
printf("%d ",b[i]);
}
}
Here is the prototype of atoi you have to use a character array but you are sending a character only.atoi(str[i])
int atoi(const char *str)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
int val;
char str[20];
strcpy(str, "98993489");
val = atoi(str);
printf("String value = %s, Int value = %d\n", str, val);
return(0);
}
Do the following:
for(i = 0; i < strlen(a); i += 2)
{
b[j] = a[i];
j++;
}
though atoi() accepts only a string argument or u can say constant char pointer and str[i] is nothing but a pointer pointing at a single character of the character array.
Therefore once we pass atoi(str[i]) , that means we are passing a character to the function, which will give an error.
Therefore you must pass the address of that particular character from where you want to convert the substring into a number i.e. atoi(&str[i]).
i tried to take input from user
input type is not determined(can be char or int)
i wanna take input and store in pointer array
while i doing that job forr each pointer i wanna take place from leap area
that is using malloc
but below code doesnot work why???
int main(void)
{
char *tutar[100][20],temp;
int i;
int n;
i=0;
while(temp!='x')
{
scanf("%c",&temp);
tutar[i]=malloc(sizeof(int));
tutar[i]=temp;
++i;
}
n =i;
for(i=0;i<=n;++i)
{
printf(" %c ",*tutar[i]);
}
printf("\n\n");
/*for(i=0;i<=n;++i)
{
printf("%d",atoi(*tutar[i]));
}
*/
}
note that;
this cite has problem when rewrite(edit) the previous mail
it is general problem or not
There are several problems in your code, including:
you declare tutar as a two-dimensional array of pointers to character, then use it as a one-dimensional array
tutar[i]=temp assigns the value of temp (a char) to tutar[i] (a pointer to char), effectively overwriting the pointer to the newly reserved memory block
you don't initialize temp, so it will have garbage value - occasionally it may have the value x, in which your loop will not execute
Here is an improved version (it is not tested, and I don't claim it to be perfect):
int main(void)
{
char *tutar[100], temp = 0;
int i = 0;
int n;
while(temp!='x')
{
scanf("%c",&temp);
tutar[i]=malloc(sizeof(char));
*tutar[i]=temp;
++i;
}
n =i;
for(i=0;i<=n;++i)
{
printf(" %c ",*tutar[i]);
}
printf("\n\n");
}
Note that unless you really need to allocate memory dynamically, you would be better off using a simple array of chars:
char tutar[100], ...
...
while(temp!='x')
{
scanf("%c",&temp);
tutar[i++]=temp;
}
...
For the sake of brevity, I incremented i within the assignment statement.