This is my first time working with dynamic arrays and I am honestly just so confused. My original array(below) works fine.
#include <stdio.h>
int main()
{
char icdC[4][10];
for(int i =0;i<4;i++){
for(int j=0;j<10;j++){
printf("What are your ICD codes [%d][%d]\n",i,j);
scanf("%s", &icdC[i][j]);
}
}
return 0;
}
However I tried converting this array into a double dynamic array (below) it doesn't seem to work correctly as it will either tell me "signal: segmentation fault (core dumped) or it just won't run.
#include <stdio.h>
#include <strings.h>
#include <stdlib.h>
#include <ctype.h>
#include <stdbool.h>
int main()
{
char** icdC;
icdC = (char**)malloc(4*10*sizeof(char));
for(int i=0;i<4;i++){
for(int j=0;j<10;j++){
printf("What are your ICD codes [%d][%d]\n",i,j);
scanf("%s", &icdC[i][j]);
}
}
return 0;
}
The issue seems to be located within icdC = (char**)malloc(4*10*sizeof(char));, as it is an incorrect reference to the second array you're trying to create.
In C there are many options to represent a 2d array, among which the possibility to
create an array of pointers, each of which points to a specific row. Then you can allocate the memory for each array using the malloc, which allows you to generate an "array of pointers".
The implementation would most likely be:
char ** icdC;
int r = 4, c = 10;
icdC = (char*) malloc(sizeof(char*) * r);
for (int i = 0; i < r; i++) {
icdC[i] = malloc(sizeof(char) * c);
}
Note: You can also do this implementation in two loops as you did above.
From here you can do a nested loop to scan the value like you've already done in your snippet. Remember that now you can access a value by indicating the index for the corresponding row and column, like this: icdC[row_num][row_column] = .....
It might look strange at the beginning, but after you get a grasp of the concept, it's all good and fun!
Related
I was working on an assignment for a simple assembler that should recognize arbitrary variable names like high programming languages. I tried to use Dynamic allocation to an array of char pointers
I am just trying to make an extensible array of strings and being able to search this array for specific strings But it gives a segmentation fault on the line of trying to compare the two strings [line: 14]
Comp(&buffer[1], Variables[i];
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define Comp(a,b) strcmp(a,b) == 0 ? 1 : 0
char buffer[255], **Variables;
int VariableIndex;
void A_instructionHandler() {
int A_Operand, test = 0;
if (buffer[0]== '#') {
for (int i = 0; i <= VariableIndex; i++) {
test = Comp(&buffer[1], Variables[i]);
if (test) {
A_Operand = i + 16;
break;
}
}
}
}
int main(int argumentCounter, char *arguments[]) {
strcpy(buffer, "#variable");
Variables = (char **)calloc(VariableIndex + 1, sizeof(char**));
A_instructionHandler();
}
Here's that code refactored into something more idiomatic:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void instruction_handler(char* buffer, char** variables) {
switch (buffer[0]) {
case '#':
// This iterates over the NULL terminated array by stopping when
// it hits a NULL pointer, or in other words *v is false.
for (char **v = variables; *v; ++v) {
// If this matches a variable name...
if (!strcmp(*v, &buffer[1])) {
// Variable matched, so show some debugging code
printf("Found variable: %s\n", *v);
return;
}
}
}
}
int main(int argc, char* argv[] ) {
// Create a simple NULL-terminated array of arbitrary size
char *variables[] = {
"variable",
NULL
};
instruction_handler("#variable", variables);
}
Where that variables array can be defined however you like, extended, shrunk, so long as the NULL terminator remains in place at the end.
Some tips based on your original code:
Don't use global variables unless you have an extremely compelling reason. No such reason existed here.
Make your functions clear in intent and purpose.
Pick a naming convention and stick to it.
Use C conventions like strcmp() and just deal with how weird it is, don't wrap that in a #define and invent your own C dialect nobody understands. You'll get used to C over time, it won't bother you as much, and you can code without driving other people on your team up the wall.
Explanations like argc expanded to argumentCounter is better expressed as a comment than an awkwardly long variable name, especially one that's very non-standard. Comments are great. Use them as much as you like!
I am trying to make a char matrix for a tic tak toe game. I allocated memory for it but I can't access it. It shows me a segmentation fault and I can't seem to figure out why.
#include <stdio.h>
#include <stdlib.h>
//function to make a char matrix
void make_board (char** board)
{
board = malloc(sizeof(char*)*3);
for(int i=0;i<3;i++)
{
board[i] = malloc(sizeof(char)*3);
}
for(int i=0;i<3;i++)
{
for(int j=0;j<3;j++)
{
board[i][j]='x';
}
}
}
//main function
int main ()
{
char ** board;
make_board(board);
/*when i try to access it it show me a segmentation fault*/
printf("%c\n",**board);
}
The reason your code is throwing a segmentation fault is related to the way in which you are passing a pointer to an array of chars into your function. In make_board, by reassigning the variable board with malloc you are telling the computer, "Make board point to an array of characters." This sounds like it would work, but when you do this you are only re-assigning the variable board within make_board. In main, the variable board remains untouched since variables are copied into functions in c, rather than passed in with the ability to edit. The other problem with your code is that you never initialize the variable board before you pass it into make_board, so you are passing in 0x0, or as interpreted by the computer, nothing.
To help you understand, this is a play by play of what the computer does in this program (keep in mind, this assumes that you add a line that allocates board in main):
Step 1: (Entering main) The user wants a char** named board. I will allocate it so that it points to the address 0x1234123412341234.
Step 2: Ok, now I should pass board into make_board. (keep in mind, it passes 0x1234123412341234 and nothing else).
Step 3: (Entering make_board) Ok, the user wants to allocate board to 3 char* types, so I will assign board to 0x1234567812345678.
This is where things have gone wrong. The rest of your code works, but when you enter main again, board is still 0x1234123412341234 rather than the value of 0x1234567812345678. This way, when you go to print **board, it has never been assigned and points to nothing, throwing a segmentation fault.
Here is my code that fixes this by passing in a char***, board_ptr, which allows make_board to create a char** pointed to by its parameter without changing it.
#include <stdio.h>
#include <stdlib.h>
//function to make a char matrix
void make_board(char*** board_ptr)
{
*board_ptr = calloc(3, sizeof(char*));
char **board = *board_ptr;
for (int i = 0; i < 3; i++) {
board[i] = calloc(3, sizeof(char));
}
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
board[i][j]='x';
}
}
}
//main function
int main(int argc, char *argv[])
{
char ***board_ptr = calloc(1, sizeof(char**));
char **board;
make_board(board_ptr);
board = *board_ptr;
printf("%c\n", **board);/* Now it works! */
}
You change board variable inside make_board, but you pass it by value, so it is not changed in the main function. You try to printf the board variable, which was initialized with garbage, thus you received segmentation fault. You should return pointer from make_board: char **board = make_board() . Or pass board variable by pointer:make_board(&board)
I'm working on DWG files using LibreDWG Library.
I succeeded to open a file, and put all the data in a dwg structure which contains many different fields.
The dwg structure description is here.
The problem comes when i try to print data from object_ref which type is Dwg_Object_Ref ** , I take the value num_object_refs to go through the object_ref array and then every element contains 3 fields (see here). I can print te value absolute_ref which is a long unsigned int, but then I need to get a value from obj which is a pointer to a dwg_object structure. From obj I want to get the value "index" and my code to do that is:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "dwg.h"
int load_dwg(char *filename, unsigned int opts) {
unsigned int i;
int success;
Dwg_Data dwg;
memset(&dwg, 0, sizeof(Dwg_Data));
dwg.opts = opts;
success = dwg_read_file(filename, &dwg);
FILE *f = fopen("lines.txt", "w");
for (i = 0; i < dwg.num_object_refs; i++)
{
struct _dwg_object *object;
object = malloc(sizeof(struct _dwg_object));
object = dwg.object_ref[i][0].obj;
printf("%d\n", object->index);
}
fclose(f);
dwg_free(&dwg);
return success;}
int main (int argc, char *argv[])
{
int i = 1;
unsigned int opts = 1;
load_dwg (argv[i], opts);
return 0;
}
This print the first value for "index" and then there is a segmentation fault.
210
Erreur de segmentation (core dumped)
but if I change the printf line inside the for to print the addresses like this:
printf("%p\n", &dwg.object_ref[i]->obj->index);
I get all the addresses without any problem.
Can anybody help me to understand the reason of this problem please?
Thanks!
Finally I found the problem.
It was in the analysed .dwg file because in the second element of the list it had a wrong address (0x00) and that's why it was stopping all the time in the same place. I was assuming that the file is correctly made and it seems to be a problem in some other files because I also tried with different dwg files so I'll add a condition on the address value before trying to have access to it.
I've got a project that involves creating a text game. I'm creating a struct for each player and putting them in an array. I'm then trying to pass in data and then pass by pointer the array to other functions, however I keep on getting segmentation faults (Although on the odd occasion working fine). I've summarised below.
#include <stdio.h>
#include <stdlib.h>
typedef struct
{
char name[9];
int cardsHeld;
int hand[8];
} Player;
void printNames(Player** playerArray)
{
for (int i = 0; i < 3; i++)
{
fprintf(stdout, "%s\n", playerArray[i]->name);
}
}
void gamesetup()
{
int count;
fprintf(stdout, "How many players will be partaking in 'The Game'? ( 1 - 5)\n");
fscanf(stdin, "%d", &count);
Player** playerArray = (Player**)malloc(sizeof(Player*) * count);
for(int i = 0; i < count; i++)
{
playerArray[i] = (Player*) malloc(sizeof(Player));
fprintf(stdout, "Please enter the name for player %d.\n\n", i + 1);
fscanf(stdin, "%s", playerArray[i]->name);
}
printNames(playerArray);
}
int main(int argc, char** argv)
{
gamesetup();
return 0;
}
My questions are;
Is the fscanf getting the address of the Player.name member? I'm getting confused whether the -> operator should deference the value of the struct member or since its in an array the address?
I'm not sure why it works sometimes but not others. If it works sometimes fundamentally it should be ok. Is the malloc function allocating memory it should not or is the fscanf putting data in the wrong place.
Thank you.
-EDIT-
Changed the code so it is in a complete program that appears to work without seg faults. I think that my issues arise from not freeing the memory before termination is messing it up next time I run it without compiling first. I'm still not sure why fscanf works as in my mind the argument playerArray[i]->name is returning the value, not the address.
I've worked it out where I was confused. Thank you for all your help in the comments.
The member I am accessing in my array is a string of chars so the first member is a pointer. By using fscanf(stdin, "%s",playerArray[i]->name); This deferenced the pointer (an address) so it works. I was getting in a muddle as it was an member of an array of structs. The segfaults were caused by me messing with the code to try and fix what already worked.
New to C, thanks a lot for help.
Is it possible to define an array in C without either specifying its size or initializing it.
For example, can I prompt a user to enter numbers and store them in an int array ? I won't know how many numbers they will enter beforehand.
The only way I can think of now is to define a max size, which is not an ideal solution...
Well, you can dynamically allocate the size:
#include <stdio.h>
int main(int argc, char *argv[])
{
int *array;
int cnt;
int i;
/* In the real world, you should do a lot more error checking than this */
printf("enter the amount\n");
scanf("%d", &cnt);
array = malloc(cnt * sizeof(int));
/* do stuff with it */
for(i=0; i < cnt; i++)
array[i] = 10*i;
for(i=0; i < cnt; i++)
printf("array[%d] = %d\n", i, array[i]);
free(array);
return 0;
}
Perhaps something like this:
#include <stdio.h>
#include <stdlib.h>
/* An arbitrary starting size.
Should be close to what you expect to use, but not really that important */
#define INIT_ARRAY_SIZE 8
int array_size = INIT_ARRAY_SIZE;
int array_index = 0;
array = malloc(array_size * sizeof(int));
void array_push(int value) {
array[array_index] = value;
array_index++;
if(array_index >= array_size) {
array_size *= 2;
array = realloc(array, array_size * sizeof(int));
}
}
int main(int argc, char *argv[]) {
int shouldBreak = 0;
int val;
while (!shouldBreak) {
scanf("%d", &val);
shouldBreak = (val == 0);
array_push(val);
}
}
This will prompt for numbers and store them in a array, as you asked. It will terminated when passed given a 0.
You create an accessor function array_push for adding to your array, you call realloc from with this function when you run out space. You double the amount of allocated space each time. At most you'll allocate double the memory you need, at worst you will call realloc log n times, where is n is final intended array size.
You may also want to check for failure after calling malloc and realloc. I have not done this above.
Yes, absolutely. C99 introduced the VLA or Variable Length Array.
Some simple code would be like such:
#include <stdio.h>
int main (void) {
int arraysize;
printf("How bid do you want your array to be?\n");
scanf("%d",&arraysize);
int ar[arraysize];
return 0;
}
Arrays, by definition, are fixed-size memory structures. You want a vector. Since Standard C doesn't define vectors, you could try looking for a library, or hand-rolling your own.
You need to do dynamic allocation: You want a pointer to a memory address of yet-unkown size. Read up on malloc and realloc.
If all you need is a data structure where in you can change its size dynamically then the best option you can go for is a linked list. You can add data to the list dynamically allocating memory for it and this would be much easier!!
If you're a beginner, maybe you don't want to deal with malloc and free yet. So if you're using GCC, you can allocate variable size arrays on the stack, just specifying the size as an expression.
For example:
#include <stdio.h>
void dyn_array(const unsigned int n) {
int array[n];
int i;
for(i=0; i<n;i++) {
array[i]=i*i;
}
for(i=0; i<n;i++) {
printf("%d\n",array[i]);
}
}
int main(int argc, char **argv) {
dyn_array(argc);
return 0;
}
But keep in mind that this is a non standard extension, so you shouldn't count on it if portability matters.
You can use malloc to allocate memory dynamically (i.e. the size is not known until runtime).
C is a low level language: you have to manually free up the memory after it's used; if you don't, your program will suffer from memory leaks.
UPDATE
Just read your comment on another answer.
You're asking for an array with a dynamically-changing-size.
Well, C has no language/syntactic facilities to do that; you either have to implement this yourself or use a library that has already implemented it.
See this question: Is there an auto-resizing array/dynamic array implementation for C that comes with glibc?
For something like this, you might want to look into data structures such as:
Linked Lists (Ideal for this situation)
Various Trees (Binary Trees, Heaps, etc)
Stacks & Queues
But as for instantiating a variable sized array, this isn't really possible.
The closest to a dynamic array is by using malloc and it's associated commands (delete, realloc, etc).
But in this situation, using commands like malloc may result in the need to expand the array, an expensive operation where you initialize another array and then copy the old array into that. Lists, and other datatypes, are generally much better at resizing.
If you're looking for array facilities and don't want to roll your own, try the following:
Glib
Apache APR
NSPR
Above given answers are correct but there is one correction, the function malloc() reserve a block of memory of specified size and return a pointer of type void* which can be casted into pointer of any form.
Syntax: ptr = (cast-type*) malloc(byte-size)
#include<stdio.h>
#include<cstdlib>
int main(int argc,char* argv[]){
int *arraySize,length;
scanf("%d",&length);
arraySize = (int*)malloc(length*sizeof(int));
for(int i=0;i<length;i++)
arraySize[i] = i*2;
for(int i=0;i<length;i++)
printf("arrayAt[%d]=%d\n",i,arraySize[i]);
free(arraySize);
}