What I know about this code is that in the void cylinder function char** argv is a array of string and numbers are stored in this. I dont know how to convert this array into the int values and then use it.
void cylinder(int argv_size, char** argv){
//comlete this code
}
int main(){
int n;
scanf("%i",&n);
char* *a = malloc(sizeof(char*) * n);
for(int i = 0; i<n;i++){
a[i] = (char *)malloc(1020 * sizeof(char));
scanf("%s",a[i]);
}
cylinder(n,a);
return 0;
}
You might want to check if some arguments/ no arguements have been passed:
if(argc==1)
printf("\nNo Command Line Argument Passed Other Than Program Name");
if(argc>=2)
{
printf("\nNumber Of Arguments Passed: %d",argc);
for(int counter=0 ; counter<argc ; counter++)
printf("\nargv[%d]: %s",counter,argv[counter]);
}
Then, to convert the passed integer(passed as a string) value use atoi, like: atoi(argv[1]) if only one integer value has been passed.
Note: use #include<stdlib.h> for atoi()
I see some disadvantage in your code:
scanf("%s",a[i]);
Should change to (see disadvantages of scanf ):
scanf("%1019s",a[i]);
//OR
fgets(a[i], 1020, stdin);
You should check the result of malloc function, and do not cast malloc as i see you allocated for a[i]:
char* *a = malloc(sizeof(char*) * n);
if(!a) {
//handle the error
return -1; // for example
}
and
a[i] = malloc(1020 * sizeof(char));
if(!a[i]) {
//handle the error
}
You have to free the memory of each a[i] and a after cylinder function to avoid memory-leaks.
For cylinder function:
void cylinder(int argv_size, char** argv){
for(int i = 0; i < argv_size; i++) {
// convert argv[i] to int by using sscanf, atoi, strol, etc.
// for example i use atoi function:
printf("value of (int)argv[i] = %d", atoi(argv[i]);
}
}
You can also find other function for converting string to int in this link How to convert a string to integer in C?
Related
I have two arrays of strings called name and subject. I want to have another array of strings whose elements are obtained by concatenating the string of the first array with the string with the same index of the other array. The new array should be the output of a function.
Here I give a code sample, but I am unable to compile due to getting errors.
I have also seen this question but I am unable to use it.
Can anyone give me a hint on how to solve this without dynamic allocation and also with dynamic allocation?
#include <stdio.h>
#include <string.h>
const int MAX = 4;
char* concancate_string(char* name,char* subject);
int main () {
char* name[] = {
"michel",
"sam",
"roy",
"romi"
};
char* subject[] = {
"physics",
"math",
"chemistry",
"biology"
};
char* p[];
p=concancate_string(name,subject);
for ( int i = 0; i < MAX; i++) {
printf("name and subject[%d] = %s\n", i, name[i] );
}
return 0;
}
char* concancate_string(char* name,char* subject)
{
for ( int i = 0; i < MAX; i++) {
strcat(name[i]," : ");
strcat(name[i],subject[i]);
}
return name;
}
resulted output array:
{
"michel : physics",
"sam : math",
"roy : chemistry",
"romi : biology"
}
Here's my attempt with dynamic allocation:
char **concancate_string(const char *name[], const char *subject[], size_t n) {
char **destin = malloc(n * sizeof *destin);
for (int i = 0; i < n; i++) {
destin[i] = malloc(strlen(name[i]) + strlen(subject[i]) + 3 + 1); // add space for " : " and terminating '\0'
sprintf(destin[i], "%s : %s", name[i], subject[i]);
}
return destin;
}
Remember to all free(destin[k]) and free(destin).
See code running on https://ideone.com/3Qb7v1
First of all, this declaration doesn't work:
char* p[]; // how much stack memory should the compiler reserve?
p=concancate_string(name,subject); // can't assign to an array
Instead, do this:
char **p = concancate_string(name, subject); // you can assign to pointers, though
Also this signature is wrong:
char* concancate_string(char* name,char* subject);
It's taking and returning arrays of char*, not single char*, so it should be:
char **concancate_string(char **name, char **subject);
Furthermore, you can't concatenate to a pointer that you assigned a string literal to. Those point to your program's binary, which is readonly. Instead, the function should look like this:
char **concancate_string(char **name, char **subject)
{
char **pointers = malloc(MAX * sizeof(char*));
for (int i = 0; i < MAX; i++) {
pointers[i] = malloc(strlen(name[i]) + strlen(subject[i]) + 4);
sprintf(pointers[i], "%s : %s", name[i], subject[i]);
}
return pointers;
}
Note how we're allocating an array for the pointers, then allocate memory for every single string, then use sprintf to assemble them (you could also use strcpy and strcat, of course).
Finally, your print is wrong. You make your p, but instead of printing that, you print name. It should instead be:
printf("name and subject[%d] = %s\n", i, p[i]);
And when you're done, the memory should be freed:
for (int i = 0; i < MAX; i++) {
free(p[i]);
}
free(p);
My suggestion to you is to write your programs one part of the time, only starting with the next part when the last part is tested and works well. If you just write the entire program without testing and then it doesn't work because there's errors all over the place, it becomes much harder to find them.
If you can assume a maximum length of each string then there is no need to use dynamic allocation. In the example below (which compiles and run) I assumed each string has a length of 100 (99 usable characters plus the \0 character).
So I defined an array using your MAX constant and 100 as char result[MAX][100] = {0};. {0} initializes all the elements to 0 (this initialization works only with 0. Then I passed this new array to the function. Note that you were defining the function parameter as char* name which means a string: you want to pass an array of strings: I redefined as concancate_string(char* name[], char* subject[], char out[MAX][100]): note the difference.
Strings are simply concatenated with strcat. There is also another function strncat which allows you to specify the max number of char to copy.
#include <stdio.h>
#include <string.h>
const int MAX = 4;
int concancate_string(char* name[], char* subject[], char out[MAX][100]);
int main () {
char result[MAX][100] = {0} ;
char* name[] = {
"michel",
"sam",
"roy",
"romi"
};
char* subject[] = {
"physics",
"math",
"chemistry",
"biology"
};
int p=concancate_string(name, subject, result);
for ( int i = 0; i < MAX; i++) {
printf("%s\n", result[i] );
}
return 0;
}
int concancate_string(char* name[], char* subject[], char out[MAX][100])
{
for ( int i = 0; i < MAX; i++) {
strcat(out[i], name[i]);
//printf("%s\n", out[i] );
strcat(out[i], " : ");
//printf("%s\n", out[i] );
strcat(out[i], subject[i]);
//printf("%s\n", out[i] );
}
retur
I'm studying C at uni and am trying to access the string (the string representation of a binary-number) that was passed into a function to convert it into the integer-representation of that string.
Eg. "011" should return 3.
The string is the first 3 bits in a bitstream that's inputted in reverse.
char * temp_holder = (char *)malloc(sizeof(char) * 4);
int index_of_holder = 0;
for(int i = 2; i >= 0; i--){
printf("%c", buffer[i]);
temp_holder[index_of_holder] = buffer[i];
}
printf("\n");
int decimalValue = fromBinaryToInt(&temp_holder, 3);
printf("DECIMAL_VALUE: %d\n", decimalValue);
The fromBinaryToInt function is:
int fromBinaryToInt(char *string[], int length){
for(int i = 0; i < length; i++){
printf("%c", *string[i]);
}
int int_rep = strtol(*string, (char **)NULL, 2);
printf("REP: %d\n", int_rep);
return int_rep;
}
The subsequent error I get is:
==21==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7ffda9f47a08 at pc 0x000000500cdf bp 0x7ffda9f47980 sp 0x7ffda9f47978
- READ of size 8 at 0x7ffda9f47a08 thread T0
I thought this could be due to the null-terminating character so I played around with modifying the length variable (+/- 1) in the for-loop within fromBinaryToInt but that hasn't changed anything.
I also considered the for-loop only accessing the first element and nothing more - but my understanding is I've sent through the memory address and the length of the block so the for-loop should have access to the indexes.
Any help would be greatly appreciated,
Cheers :)
In this code:
int index_of_holder = 0;
for(int i = 2; i >= 0; i--){
printf("%c", buffer[i]);
temp_holder[index_of_holder] = buffer[i];
}
index_of_holder is never changed, so all the characters are put in temp_holder[0]. The rest of temp_holder remains uninitialized.
This:
int fromBinaryToInt(char *string[], int length)
declares string to be an array of pointers to char. It is indeed passed &temp_holder, which may be considered to be a pointer to the first element of an array of one pointer to char. However, a more normal usage is to declare a simple pointer to char
int fromBinaryToInt(char *string, int length)
and pass it temp_holder, as in fromBinaryToInt(temp_holder, 3).
As it is, where it is used here:
printf("%c", *string[i]);
This takes element i of the array. When i is 0 in the loop, that is fine, it takes the first element, which exists and is a pointer to char, and then deferences it with * and prints that. However, when i is 1, it attempts to take the second element of the array. That element does not exist, and the resulting behavior is undefined.
If the parameter were merely char *string, then this printf could be:
printf("%c", string[i]);
and, in calling strtol, you would simply pass string rather than *string:
int int_rep = strtol(string, (char **)NULL, 2);
Firstly, bug in below line, index_of_holder remains same all the time, please increment it.
temp_holder[index_of_holder] = buffer[i];
Secondly, in fromBinaryToInt() string is single pointer only so you can't do *string[i]); in the next printf statement.
Here is the working code
int fromBinaryToInt(char *string, int length){
for(int i = 0; i < length; i++){
printf("%c", string[i] ); /*since string is single pointer now you can do like before you did */
}
int int_rep = strtol(string, (char **)NULL, 2);
printf("REP: %d\n", int_rep);
return int_rep;
}
int main() {
char * temp_holder = (char *)malloc(sizeof(char) * 4);
char buffer[4] ="011";
int index_of_holder = 0;
for(int i = 2; i >= 0; i--){
printf("%c", buffer[i]);
temp_holder[index_of_holder] = buffer[i];
index_of_holder++;
}
printf("\n");
int decimalValue = fromBinaryToInt(temp_holder, 3);/* no need to pass address of temp_holder */
printf("DECIMAL_VALUE: %d\n", decimalValue);
return 0;
}
Sorry for my question, I know there are a lot similars but I didn't found any that is simple enaugh to help me.
I've started coding in C and try to solve a simple exercise: Read an integers array from command line, sum the elements using the function array_sum and print result. (input example array of 3 elements: 3 0 1 2)
int array_sum(int *array, size_t size);
int main(int argc, char **argv){
int sum=array_sum(argv, argc);
printf("array_sum: %i\n", sum);
return 0;
}
my problem is that argv is a char array and the function want an integer array.
Should I convert elements one by one in a new int array? There are better ways?
argv is an array of pointers to C strings. You need to convert the strings into integers first. You can do something like this:
int array_sum(int *array, size_t size);
int main(int argc, char **argv){
int *num_arr = malloc((argc - 1) * sizeof *num_arr);
for (int i = 0; i < argc - 1; ++i)
num_arr[i] = atoi(argv[i+1]);
int sum = array_sum(num_arr, argc - 1);
printf("array_sum: %i\n", sum);
free(num_arr);
return 0;
}
The only way to make the code in main shorter is by moving the conversion loop into a separate function that returns the malloced pointer.
In your code, char *argv[] is an array of char* pointers supplied from the command line. In order to convert the numbers supplied, you can use the following:
atoi(), which converts string arguement to an integer type.
Or strtol(), which converts the initial part of a string to a long int, given a base.
Other special functions from C99, alot of which are described in this post.
Since atoi() has no error checking, it is best to use strtol(), which allows extensive error checking.
You should store these converted numbers in a dynamically allocated int* pointer, which will need to be allocated on the heap using malloc(), which was suggested by #StoryTeller in his answer. You could also just declare an array on the stack, such as int arr[n]. The problem arises when you want to return this array in a function, which is not possible. Using a pointer in this case would allow more flexibility for abstraction.
malloc()allocates block of memory on the heap, and returns a void* pointer to it.
Note: malloc() should always be checked, as it can return NULL. You need to also free() this pointer at the end.
Here is some example code:
#include <stdio.h>
#include <stdlib.h>
#define BASE 10
/* Guessed that your function would look like this */
int array_sum(int *array, size_t size) {
int sum = 0;
for (size_t i = 0; i < size; i++) {
sum += array[i];
}
return sum;
}
int main(int argc, char *argv[]) {
int *arr = NULL;
char *endptr = NULL;
int check, sum;
size_t ndigits = (size_t)argc-1;
/* allocate pointer */
arr = malloc(ndigits * sizeof *arr);
if (arr == NULL) {
fprintf(stderr, "Cannot %zu spaces for integers\n", ndigits);
exit(EXIT_FAILURE);
}
for (size_t i = 0; i < ndigits; i++) {
/* sufficient checking for strtol(), more can possibly be added here */
check = strtol(argv[i+1], &endptr, BASE);
if (endptr != argv[i+1] && *endptr == '\0') {
arr[i] = check;
}
}
sum = array_sum(arr, ndigits);
printf("array_sum: %d\n", sum);
/* pointer is free'd */
free(arr);
arr = NULL;
return 0;
}
Example input:
$ gcc -Wall -Wextra -std=c99 -o sumcommands sumcommmands.c
$ ./sumcommands 3 2 1
Output:
array_sum: 6
Note: You can use more error checking for strtol() on the Man page.
Why do you need to pass an int array as argument to the function ? No need to create an extra int array when you can simply do this :
int array_sum(char **argv, int argc){
int sum = 0;
for(int i = 0;i < argc - 1;i++){
sum += atoi(argv[i])
}
return sum;
}
You can use atoi() function to convert char ** array to **int . what i see here is each integer you type is converting into string rather than char.
New to C here and would appreciate if I could get some pointers.
I'm trying to initialise an array inside an if statement, and then print the values of the array externally - but I know the scope will be lost after the if block ends. I've tried creating the array with pointers. The reason I'm doing it inside the if statement is because the size of the array depends on a value calculated during runtime.
E.g.:
void createArray() {
int userInput;
printf("%s\n", "Please enter a value:");
scanf("%d\n", userInput);
if (userInput > 10) {
int array[userInput];
}
int i;
for (i = 0; i < userInput; i++) {
array[i] = i;
}
}
int i;
for (i = 0; i < sizeof(array)/sizeof(array[0]); i++) {
printf("%d\n", array[i]);
}
However because the array is declared inside a method, I obviously lose scope of it when it comes to the final for loop to print - thus an error occurs. I've tried creating a pointer variable int *array as a global variable, and inside the if statement, just staying array = int[10] but obviously this won't work.
This isn't my exact code, I've recreated a minimal example that shows my error so some syntax may be wrong here - apologies for that.
Any help would be appreciated.
One question you have to consider in your code is what happens if userInput is less than or equal to 10? You iterate over userInput elements of an array that was not declared.
One simple way of handling this is to make a large array at the beginning of your function and then use just the first userInput elements of it. This approach has obviously its limitations (e.g. userInput can't be larger than the size of the array, and you should make sure it won't be, otherwise bad things may happen), but is simple.
Another approach involves using dynamic memory allocation. This is done by using the malloc function:
int *array = malloc(100 * sizeof(int));
The code above allocates memory for 100 ints, basically creating an array of 100 elements. Then, you can use the array as usual. But, make sure you free it after you're done:
free(array);
Note that using this approach you'd need to declare the pointer first:
int *array;
if (userInput > 10) {
array = malloc(userInput * sizeof(int));
}
Below you can find a small proof of concept program. Note that instead of a global variable, the pointer value can be returned from the alloc function.
#include <stdio.h>
#include <stdlib.h>
int *arr;
void alloc() {
arr = malloc(10 * sizeof(int));
}
void assign() {
for (int i = 0; i < 10; i++)
arr[i] = i + i;
}
void print() {
for (int i = 0; i < 10; i++)
printf("%d\n", arr[i]);
}
int main(int argc, char *argv[])
{
alloc();
assign();
print();
free(arr);
return 0;
}
This allocates an array of int to the pointer intary. The pointer may be passed to other functions from main(). In main, userInput stores the number of int allocated.
#include <stdio.h>
#include <stdlib.h>
int *createArray( int *userInput);
int main( int argc, char *argv[])
{
int i;
int userInput = 0;
int *intary = NULL;
if ( ( intary = createArray ( &userInput)) != NULL ) {
for (i = 0; i < userInput; i++) {
intary[i] = i;
printf ( "%d\n", intary[i]);
}
free ( intary);
}
return 0;
}
int *createArray( int *userInput) {
int *array = NULL;
printf("%s\n", "Please enter a value:");
scanf("%d", userInput);
if ( *userInput > 10) {
if ( ( array = malloc ( *userInput * sizeof ( int))) == NULL) {
printf ( "could not allocate memory\n");
*userInput = 0;
return NULL;
}
}
else {
*userInput = 0;
return NULL;
}
return array;
}
You don't need some pointers, just one, (int* arr) and malloc(),a dynamic memory allocation function.
Note: You shouldn't use "array" as a variable name as it may create problems. So we'll name our variable arr.
If you're unfamiliar with it, i will explain the code too.
First add #include <stdlib.h> header file, which contains malloc().
Then declare a pointer of type int int* arr, we have named it arr in the createArray() scope.
We'll allocate the space required in the if condition with malloc() function, like :
void createArray() {
int userInput;
int* arr; // declare arr pointer
printf("%s\n", "Please enter a value:");
scanf("%d\n", userInput);
if (userInput > 10) {
arr = (int*) malloc ( userInput * sizeof(int) ); // explained below
}
int i;
for (i = 0; i < userInput; i++) {
arr[i] = i;
}
}
free(arr) // don't forget to free after using
[NOTE] This code is untested.
arr = (int*) malloc ( userInput * sizeof(int) );
This line may seem cryptic at first, but what it does is pretty simple , it allocates some memory dynamically on the heap.
The size of this memory is given by 'userInput * sizeof(int)', sizeof() function specifies the size of int on the given machine multiplied by userInput by the user,
Then, it is typecasted to int* type so that we can store the address in our int* type pointer arr.
[UPDATE] you can use arr = malloc ( userInput * sizeof(int) ); instead as suggested in comments, here is why Do I cast the result of malloc?
How do you make 2 array strings into 1 array string, where I can print out all the 52 playing cards?
my code:
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<string.h>
int main() {
char deck[52];
char suits[] = {"Hearts","Diamonds","Clubs","Spades"};
char values[]= {"Ace","Two","Three","Four","Five","Six",\
"Seven","Eight","Nine","Ten","Jack",\
"Queen","King"};
int V, S, d = 0;
char string;
for ( S= 0; S <4; S++) {
for (V =0; V< 13; V++) {
string = strcat( values[V], suits[S]);
deck[d] = string;
printf("%s\n", string);//prints out all the 52 playing cards
d++;
}
}
return 0;
}
When I executed the program, the problem comes up which asks me to debug the program or close the program, where I closed the program in the end, which returns nothing. Can you please give me the answer which works?
Check the below code which fixes the issues in your code:
The problem with your code is you try to modify the actual string before printing and because of this there is a modified string in the next iteration. So just copy the values and suits to array and print it out as shown below.
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<string.h>
int main()
{
int i=0;
char deck[30] = "";
char suits[][30] = {"Hearts","Diamonds","Clubs","Spades"};
char values[][30]= {"Ace","Two","Three","Four","Five","Six",
"Seven","Eight","Nine","Ten","Jack",
"Queen","King"};
int V, S;
for ( S= 0; S <13; S++)
{
for (V =0; V< 4; V++){
memset(deck,0,sizeof(deck));/* Clear the buffer before writing new value*/
strcpy( deck, values[S]);
strcat(deck,suits[V]);
printf("%s\n", deck);//prints out all the 52 playing cards
i++;
}
}
printf("Number of playing cards: %d\n",i);
return 0;
}
strcat() returns a char *, a pointer to a char, not a char.
You are not even required to even consider the return value of strcat() since the destination pointer (first argument) will now contain the concatenated string, assuming enough memory is already allocated.
So here in your code, you are trying to put the concatenated string to values[V] which could fail when memory already allocated to it becomes insufficient.
The best method would be to allocate some memory (as you did with deck[]) and set it all to zeroes. Then keep strcat()ing there.
strcat(deck, values[V]);
strcat(deck, suits[S]);
An alternative to using strcpy and strcat is to use sprintf.
#include<stdio.h>
#include<string.h>
#define NUM_SUITS 4
#define CARDS_PER_SUIT 13
#define TOTAL_CARDS (NUM_SUITS * CARDS_PER_SUIT)
int main()
{
char deck[TOTAL_CARDS][24];
char* suits[NUM_SUITS] = {"Hearts","Diamonds","Clubs","Spades"};
char* values[CARDS_PER_SUIT]= {"Ace","Two","Three","Four","Five","Six",
"Seven","Eight","Nine","Ten","Jack",
"Queen","King"};
int s, c, i;
for(s = 0; s < NUM_SUITS; s++)
{
for(c = 0; c < CARDS_PER_SUIT; c++)
{
sprintf(deck[(s * CARDS_PER_SUIT) + c], "%s of %s", values[c], suits[s]);
}
}
for(i = 0; i < TOTAL_CARDS; i++)
{
printf("%s\n", deck[i]);
}
return 0;
}