Printing array of struct Segmentation fault - c

I'm trying to print my struct. I want it to show:
id: BBB-188
brand: BMW
pic: 1 2 3.
Right now the result is this:
id: BBB-188
name: BMW
Segmentation fault: 11.
Does anyone know what is wrong with my code?
#define MAX 10000
#define IDSIZE 11
#define BRANDSIZE 50
#define PICSIZE 10
typedef struct{
char id[IDSIZE+1];
char brand[BRANDSIZE+1];
int *pic;
} Car;
void printCar(Car *pCar,int carcount, int imagecount) {
printf("id: %s \n",pCar->id);
printf("brand: %s \n",pCar->brand);
for(int i=0; i< imagecount; i++){
printf("pic: %d \n",pCar->pic[i]);
}
}
Car initCar(char itsId[],char itsBrand[],int itsPic, int imagecount){
Car newCar;
strcpy(newCar.id, itsId);
strcpy(newCar.brand, itsBrand);
for (int i = 0; i < imagecount; i++){
newCar.pic = itsPic;
}
return newCar;
}
int main(void){
int carcount=0;
int imagecount=0;
int test[3]={1,2,3};
Car myCar = initCar("BBB-188","BMW", test, 3 );
carcount=1;
imagecount=3;
printCar(&myCar,carcount,imagecount);
return 0;
}

The handling of pic is broken and very confusing.
You seem to want to represent it as an array of integers, but you don't store the length. Thus it has to be always three, but then you can just use an array in the structure, i.e.:
int pic[3];
instead of
int *pic;
Also the assignment inside initCar() makes no sense, you're looping but simply assigning the same integer value (!) to the pointer imagecount times, no data is being copied.
If you want the length of the picture array to really be variable, you must store the length and allocate memory for holding the numbers. So in initCar() you must have:
newCar.pic = malloc(imagecount * sizeof *newCar.pic);
memcpy(newCar.pic, itsPic, imagecount * sizeof *newCar.pic);
but then itsPic must of course be of type const int *.

You need to pass itsPic as a pointer in initCar. If you're doing so, you don't need the for loop for the affectation.
Car initCar(char itsId[],char itsBrand[],int* itsPic, int imagecount){
Car newCar;
strcpy(newCar.id, itsId);
strcpy(newCar.brand, itsBrand);
//for (int i = 0; i < imagecount; i++){
newCar.pic = itsPic;
//}
return newCar;
}

Related

copy a struct array to another (not struct) array in C

I am trying to copy name array to another array and print it
#include <stdio.h>
typedef struct
{
char name[100];
int age;
} data;
int main() {
char new_array[100];
data people[] = {{ "john", 12},{" kate", 15}};
for(int i =0; i < sizeof(people); i++) {
new_array[i] = people[i].name;
printf("%c ", new_array[i]);
}
return 0;
}
But it gives me an error:
error: assignment to ‘char’ from ‘char *’ makes integer from pointer without a cast [-Werror=int-conversion]
new_array[i] = people[i].name;
^
How do I fix this?
You can change:
char new_array[100];
to:
char new_array[10][100]; // for maximum 10 strings
Then using strcpy to copy string in c. If you want to calculate the number of elements of array, using:
sizeof(people)/sizeof(people[0]);
Then, the for loop becomes:
for(int i =0; i < sizeof(people)/sizeof(people[0]); i++) {
strcpy(new_array[i],people[i].name);
printf("%s ", new_array[i]);
}
You are trying to assign a string to a char which is described by your error. To copy a string to a char array, you should use strcpy().
Also, your new_array is a mere array of characters and has no way to differentiate two different names.
To make it an array of strings, you should use a 2D array where you can index the row to get different strings like below
char new_array[10][100]
This makes an array of 10 strings of 100 characters each.
Also, your iteration over the array of structure is messy.
To get correct size of array of structure, you should use
int size = sizeof(people)/sizeof(people[0])
So, your final code becomes-
#include <stdio.h>
#include <string.h>
typedef struct
{
char name[100];
int age;
} data;
int main() {
char new_array[10][100];
data people[] = {{ "john", 12},{" kate", 15}};
for(int i =0; i < sizeof(people)/sizeof(people[0]); i++) {
strcpy(new_array[i],people[i].name);
printf("%s ", new_array[i]);
}
return 0;
}

Incrementing the pointer to string array returns NULL

I'm trying to pass an array of strings to a function to print to the screen. The first string prints fine. The proceeding strings, however, are null and thus don't print anything. If I get the pointer directly to the first string instead of the array I can increment it by the size of of the character array and everything prints correctly. If I try to increment the pointer to the array of strings that's where I get the null. Why does this happen and how can I correctly print the array. Also I'm using visual studio if that is affecting it any at all given the C standard it uses.
I don't think the error lies with the call because the pointer passed points to the string array address.
//How I'm passing the array
char headings[4][20] = { "Name", "Record Number", "Quantity", "Cost"};
int widths[4] = {20, 20, 20, 20 };
headers(&headings[0][0], &widths[0], 4);
//Function
void headers(char **heads, int *columnWidths, int noOfColumns) {
int headLength = 0;
printf("|");
for (int i = 0; i < noOfColumns; i++) {
headLength += printf("%*s|", *columnWidths, heads);
columnWidths++;
heads ++;
}
printf("\n");
for (int i = 0; i < headLength+1; i++) {
printf("-");
}
printf("\n");
}
This is the output that I get:
| Name| | | |
but I'm expecting this output:
| Name| Record Number| Quantity| Cost|
If you have a 2D Array heading, your headers function should also accept a 2D array. Although arrays generally decay to pointers when passed to functions, the type char** heads is not the same as char headings[4][20]. And your compiler should warn you about it also.
The following bit of code prints the correct output.
#include <stdio.h>
#include <string.h>
//Function
void headers(char heads[4][20], int *columnWidths, int noOfColumns) {
int headLength = 0;
printf("|");
for (int i = 0; i < noOfColumns; i++) {
headLength += printf("%*s|", *columnWidths, *heads);
columnWidths++;
heads ++;
}
printf("\n");
for (int i = 0; i < headLength+1; i++) {
printf("-");
}
printf("\n");
}
int main(){
char headings[4][20] = { "Name", "Record Number", "Quantity", "Cost"};
int widths[4] = {20, 20, 20, 20};
headers(headings, &widths[0], 4);
}
Note: you could also change the headers function to accept char heads[][20], but not char[][] as that would give you an obvious compiler error.
You would need to pass headings into your function, not the address of the first character of the first function. But in C multidimensional arrays are a complete distinct type and the memory layout differs significantly from array of char *.
This is a working variant, which supports arbitrary dimensions, unlike the accepted solution which only supports the array dimensions 4 string with 20 chars each:
#include <stdio.h>
#include <string.h>
//Function
void headers(const char **heads, int *columnWidths) {
int headLength = 0;
printf("|");
while (*heads) {
headLength += printf("%*s|", *columnWidths, *heads);
columnWidths++;
heads ++;
}
printf("\n");
for (int i = 0; i < headLength+1; i++) {
printf("-");
}
printf("\n");
}
int main(){
const char *headings[] = { "Name", "Record Number", "Quantity", "Cost", 0};
int widths[4] = {20, 20, 20, 20};
headers(headings, &widths[0]);
}
I don't think the error lies with the call because the pointer passed points to the string array address.
No. The pointer to the string array is called headings. This is an array of char, with two dimensions. It is not possible to iterate over the individual strings without knowledge of the layout of the array.
Instead it is usually better to define an array of char * and initialize this with the individual strings. You can see how the definition of the array content looks exactly the same as in the multidimensional array variant, but the memory layout is very different, and it is now possible to iterate over the strings like you initially intended.

Understanding part of an algorithm

Below is a part of an algorithm i was given to use for a project, but as it's my first time to use an algorithm i don't understand the following lines. Please will need your help.
For i=1 to n do
t[i] .mark <-- 0
t[i] .num <-- -1
End
This pseudo code can be translated to C
Use struct
struct cm{
int mark;
int num;
};
#define N 10
int main(void)
{
struct cm t[N];
for (int i=0;i<N;i++){
t[i].mark = 0;
t[i].num = -1;
}
//print your struct elements field
for (int i=0;i<N;i++){
printf("%d: %d, %d\n",i ,t[i].mark, t[i].num);
}
}
We have an array of struct because of we need each element of it have two field of data (i.e. mark,num).
struct cm t[N]; define a N length array of structure cm.
In loop we assign to each field of array elements proper values.
For more readability you can use typedef instead of using struct to define your desire data structure in this case.
typedef vs struct
Use typedef
typedef struct typecm{
int mark;
int num;
}typecm;
#define N 10
int main(void)
{
typecm s[N];
for (int i=0;i<N;i++){
s[i].mark = 0;
s[i].num = -1;
}
//print values
for (int i=0;i<N;i++){
printf("%d: %d, %d\n",i ,s[i].mark, s[i].num);
}
}
The "t" seems to be an array of objects, and "mark" and "num" are properties of the object.
This may help you:
From an array of objects, extract value of a property as array

Array pointers and functions

I have to write a C program to do the following:
Write a function that takes three arguments: a pointer to the first
element of a range in an array, a pointer to the element following
the end of a range in an array, and an int value. Have the function
set each element of the array to the int value.
My code is not working. Here is what I have so far. Any help is appreciated.
#include <stdio.h>
#include <iostream>
int listNumbers[3]{ 1,2,3 };
void Sorter(int *first, int * last, int *value);
int * first = &listNumbers[0];
int * last = &listNumbers[2];
int value;
int main() {
printf("your list numbers are:\n");
int i;
for (int i = 0; i < 3; ++i) {
printf("%d", listNumbers[i]);
}
printf("\n");
printf("enter an integer:\n");
scanf_s("%d", &value);
Sorter( first, last, &value);
printf("your new list numbers are:\n");
int j;
for (int j = 0; j < 3; ++j) {
printf("%d", listNumbers[j]);
}
printf("\n");
system("PAUSE");
return 0;
}
void Sorter(int *first, int * last, int *value) {
int i=0;
printf("value = %d\n", &value);
*first = value;
while (i <= *last) {
*(first + i) = value;
i++;
}
}
First, work out the different between the 2 pointers.
int count = last - first + 1;
The compiler will automatically divide by the size of an integer. We add 1 to make the range inclusive. Now just iterate through each element:
for (int i = 0; i < count; i++) {
first[i] = value;
}
Also, why are you passing the value as a pointer? This should just be a value.
void Sorter(int *first, int *last, int value) {
And when you call it...
Sorter(first, last, value);
Your Sorter function does not satisfy the problem criteria. The parameters are supposed to be two pointers into an array, and an int. Your function instead accepts three pointers.
You could nevertheless have made it implement at least the apparent spirit of the exercise, by using the value to which the third argument points as the fill value, but you don't do that. Instead you assign the pointer itself to each array element. That ought to at least elicit a warning from your compiler, and you ought not to be ignoring its warnings, especially when your code it not doing what you think it should.
Furthermore, the last pointer is expected to point to just past the last element to set, but you use it as if it points to an integer offset from the start pointer. This is almost the opposite of the previous problem: here, you need to use the pointer value itself, not the int to which it points.

Creating an array of int arrays in C?

Let us say I have the following method prototype:
void mix_audio(int *vocal_data_array, int *instrumental_data_array, int *mixed_audio_array, FOURTH ARGUMENT)
{
}
How would I:
Initialize an array_of_arrays before the above argument so as to pass it as the fourth argument?
In the method, make it so that the first value of my array_of_arrays is the array called vocal_data, that the second value of my array is instrumental_data_array and the third value is mixed_audio_array.
How would I later then loop through all the values of the first array within the array_of_arrays.
I hope I'm not asking too much here. I just thought it would be simple syntax that someone could spit out pretty quickly :)
Thanks!
EDIT 1
Please note that although I've showed by my example an array_of_arrays of length 3 I'm actually looking to create something that could contain a variable length of arrays.
Simple array of arrays and a function showing how to pass it. I just added fake values to the arrays to show that something was passed to the function and that I could print it back out. The size of the array, 3, is just arbitrary and can be changed to whatever sizing you want. Each array can be of a different size (known as a jagged array). It shows your three criteria:
Initialization, Assigning values to each index of arrayOfArrays, The function demonstrates how to extract the data from the array of arrays
#include <stdio.h>
void mix_audio(int *arr[3]);
int main() {
int *arrayOfArrays[3];
int vocal[3] = {1,2,3};
int instrumental[3] = {4,5,6};
int mixed_audio[3] = {7,8,9};
arrayOfArrays[0] = vocal;
arrayOfArrays[1] = instrumental;
arrayOfArrays[2] = mixed_audio;
mix_audio(arrayOfArrays);
return(0);
}
void mix_audio(int *arr[3]) {
int i;
int *vocal = arr[0];
int *instrumental = arr[1];
int *mixed_audio = arr[2];
for (i=0; i<3; i++) {
printf("vocal = %d\n", vocal[i]);
}
for (i=0; i<3; i++) {
printf("instrumental = %d\n", instrumental[i]);
}
for (i=0; i<3; i++) {
printf("mixed_audio = %d\n", mixed_audio[i]);
}
}
From your question it sounds like you actually want a struct containing your arrays, something like:
struct AudioData {
int* vocal_data_array;
unsigned int vocal_data_length;
int* instrumental_data_array;
unsigned int instrumental_data_length;
int* mixed_audio_array;
unsigned int mixed_audio_length;
};
For the array allocation using the example of an array of integers:
int** x = malloc (sizeof (int*) * rows);
if (! x) {
// Error
}
for (int i = 0; i < rows; ++i) {
x[i] = malloc (sizeof (int) * columns);
if (! x[i]) {
// Error
}
}

Resources