The dynamically allocated array of chars that i'm trying to create is not working good - c

I'm trying to create a program that asks for a letter and creates a dynamical array of the amount passed by the user, but i'm having some trouble since the array i am creating is always giving me no length. What am i doing wrong?
PD: The code is not finished, i want to know my error before cotinuing.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define OK 0
#define ERROR -1
int pedir_memoria(char **arreglo, int cant_letras);
int cargar_letra(char letra,char**arreglo,int cant_letras);
int main(int argc, char **argv)
{
char *arreglo = NULL;
char letra;
int cant_letras = 0, estado,largo;
do
{
printf("ingrese letras: ");
scanf(" %c", &letra);
cant_letras++;
estado = pedir_memoria(&arreglo, cant_letras);
if(estado != ERROR)
printf("memoria solicitada correctmanete \n");
// estado = cargar_letra(letra,&arreglo,cant_letras);
}
while (letra > 'A' && letra < 'z');
largo = strlen(arreglo);
printf("arr length: %d \n",largo);
return 0;
}
int pedir_memoria(char **arreglo, int cant_letras)
{
int estado = ERROR;
char *aux = NULL;
if (arreglo != NULL && cant_letras != 0)
{
if(cant_letras == 1)
{
(*arreglo) = (char*)malloc(sizeof(char) * cant_letras);
if (*arreglo != NULL)
estado = OK;
}
else
{
aux = (char*)realloc(*arreglo,sizeof(char) * cant_letras);
if(aux != NULL)
{
*arreglo = aux;
estado = OK;
}
}
}
return estado;
}
int cargar_letras(char letra,char**arreglo,int cant_letras)
{
int estado;
if(arreglo != NULL && cant_letras != 0)
{
(*(arreglo[cant_letras - 1])) = letra;
estado = OK;
}
return estado;
}
i tried to directly use a big malloc with a magic number instead of giving the amount of characters and to print the length of the array from the function itself and is still throwing me the cero value.

Your issue comes from the strlen fnc, the function counts till it finds a '\0' in your string. When you malloc the array is set to random values, so it can't find when it ends. The better way to print the length of your array would be to use directly cant_letras.

Related

How to get whole structure from function?

This is my code:
#include <stdio.h>
typedef struct
{
char name[100];
char number[100];
} contact_t;
void empty_array(char *line)
{
for (int j = 0; line[j] != '\0'; j++)
{
line[j] = '\0';
}
}
void read_text(contact_t *contact)
{
int c, cnt = 0;
int i = 0;
char line[100];
do
{
c = getchar();
if ( (c == '\n') || (c == EOF))
{
if( cnt % 2 == 0)
{
for(int j = 0; line[j] != '\0'; j++)
contact -> name[j] = line[j];
}
else
{
for(int j = 0; line[j] != '\0'; j++)
contact -> number[j] = line[j];
}
empty_array(line);
i = 0;
cnt++;
}
line [i] = c;
i++;
} while (c != EOF);
}
int main()
{
contact_t contact = {"x", "0"};
int *j_ptr;
read_text(&contact);
printf("%s", contact.name);
printf("%s", contact.number);
return 0;
}
I am reading a text file(6 lines, name and number, name and number...) from standard input. Then I assign every second line(starting from the first) from that text file to structure contact.name and the rest are I assign to contact.number. So I have several 3 contact structures. I managed to pass to main only the last one, because I don't know how to get acces to int cnt and again make a for cycle.
This is what last prints give me:
John Green
254454556
UPDATE:
I am sorry for not being clear enough as I was writing this question in a hurry. This code is a part of school project and we are not allowed to work with dynamically allocated memory or use fscanf, fopen, qsort, lsearch, bsearch and hsearch etc. Basically, I would just like to use pointers to index of array line and then in main function use a for cycle again to pass all structures from the function read_text to main function of the program.
A few issues ...
main only provides space for one contact entry
read_text needs to use a dynamic array (vs. overwriting the same entry)
read_text needs to return the list pointer and the count to the caller (e.g. main)
The method used in read_text is a bit convoluted.
Style fixes:
contact -> name --> contact->name
list [i] --> list[i]
Here is the refactored code. It is annotated:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct {
char name[100];
char number[100];
} contact_t;
int
read_text(contact_t **listp)
{
char buf[1000];
contact_t *list = NULL;
char *cp = NULL;
int cnt = 0;
// loop on input until EOF
while (fgets(buf,sizeof(buf),stdin) != NULL) {
// increase size of list
++cnt;
list = realloc(list,sizeof(*list) * cnt);
// handle error
if (list == NULL) {
perror("realloc/increase");
exit(1);
}
// point to current record
contact_t *contact = &list[cnt - 1];
// get first name
contact->name[0] = 0;
cp = strtok(buf," \n");
if (cp == NULL)
break;
strcat(contact->name,cp);
// add separater
strcat(contact->name," ");
// get last name
cp = strtok(NULL," \n");
if (cp == NULL)
break;
strcat(contact->name,cp);
// get number
cp = strtok(NULL," \n");
if (cp == NULL)
break;
strcpy(contact->number,cp);
}
// trim to actual amount stored (if error)
if ((cp == NULL) && (cnt > 0)) {
--cnt;
list = realloc(list,sizeof(*list) * cnt);
if (list == NULL) {
perror("realloc/trim");
exit(1);
}
}
// give caller the list pointer
*listp = list;
return cnt;
}
int
main(void)
{
int cnt;
contact_t *list;
cnt = read_text(&list);
// print all entries read in
for (int idx = 0; idx < cnt; ++idx) {
contact_t *contact = &list[idx];
printf("'%s' '%s'\n",contact->name,contact->number);
}
return 0;
}
Here is the test input I used:
John Green 254454556
Fred Smith 8765309
Bob Jones 99728967341
Mary Gallagher 4329268757
Here is the program output:
'John Green' '254454556'
'Fred Smith' '8765309'
'Bob Jones' '99728967341'
'Mary Gallagher' '4329268757'
UPDATE:
I am sorry, I should have clarified that I cannot use dynamically allocated memory. Malloc, calloc or also fsangf is not available –
gregalz
Okay, no malloc et. al. Ironically, I was going to use a predefined fixed size array. But, decided to use a dynamic array instead ;-)
Not sure what fsangf is. So, I'll assume that's fscanf. If you're heavily restricted, maybe you should edit your question and post what you can and can not use.
Here's the code that uses just a fixed array:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct {
char name[100];
char number[100];
} contact_t;
#define NLIST 1000
contact_t list[NLIST];
int
read_text(contact_t *list,int max)
{
char buf[1000];
char *cp = NULL;
int cnt = 0;
// loop on input until EOF
while (fgets(buf,sizeof(buf),stdin) != NULL) {
// don't overflow the max size
if (cnt >= max)
break;
// point to current record and increase list count
contact_t *contact = &list[cnt++];
// get first name
contact->name[0] = 0;
cp = strtok(buf," \n");
if (cp == NULL)
break;
strcat(contact->name,cp);
// add separater
strcat(contact->name," ");
// get last name
cp = strtok(NULL," \n");
if (cp == NULL)
break;
strcat(contact->name,cp);
// get number
cp = strtok(NULL," \n");
if (cp == NULL)
break;
strcpy(contact->number,cp);
}
// trim to actual amount stored (if error)
if ((cp == NULL) && (cnt > 0))
--cnt;
return cnt;
}
int
main(void)
{
int cnt;
cnt = read_text(list,NLIST);
// print all entries read in
for (int idx = 0; idx < cnt; ++idx) {
contact_t *contact = &list[idx];
printf("'%s' '%s'\n",contact->name,contact->number);
}
return 0;
}

Create a function that returns an array in which each cell contains the address of a string (representing a word)

I need some advice concerning this coding exercise:
Write a function that splits a string into words. Separators will all
be non-alphanumeric characters. The function returns an array in which
each cell contains the address of a string (representing a word). The
last cell must be NULL to terminate the array.
Two things I need help are :
How does my function make a proper return of the array to my main function
and does the malloc array is used properly ?
I think I've missed up the pointer parts because there are errors showing up during compilation.
If you have any idea, please let me know, thanks !
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
char **my_str_to_word_array(const char *str)
{
char* tab_address = NULL;
int j = 0; /*Nombre de mots*/
int i = 0;
char ptr = 0;
for( i = 0; str[i] != " "; i++)/*Compter le nombre de mots dans la string*/
if(*str[i] = " ")
j++;
tab_address = malloc(sizeof(char) * j); /*tab avec tous les mots compter par j*/
if (tab_address == NULL)
exit(0);
for ( i = 0; str[i] != " "; i++) /*Stocker les adresse dans un tableau */
if(str[i] = " ")
{
i++;
tab_address[j] = ptr;
}
else if (*str[i] = "\0")
break;
return ptr;
free(tab_address);
}
int main(void)
{
char str[50] = "Hello world";
my_str_to_word_array(str);
return 0;
}
It seems to work. Note that the code assume str is not NULL.
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h> // added for usage of isalpha function
char **my_str_to_word_array(const char *str)
{
char** tab_address = NULL; // FIXED: this need to be an array of char* so char**
int j = 0; /*Nombre de mots*/
int i = 0;
//char ptr = 0; // FIXED: This not needed
for(i = 0; str[i] != '\0'; i++) // FIXED: you want to go until the end of the string
if(isalpha(str[i])) // FIXED: you want to check for non alphanumeric here not space
j++;
tab_address = malloc(sizeof(char*) * (j + 1)); // FIXED: you want to allocate char* -s not char -s
if (tab_address == NULL)
exit(0);
tab_address[0] = str; // ADDED: the first word should be at the start of the string
j = 1; // FIXED: reinitialize j to 1
for ( i = 0; str[i] != '\0'; i++) // FIXED: you want to go until the end of the string
if(!isalpha(str[i])) // FIXED: you want to check for non alphanumeric here not space
tab_address[j++] = &str[++i]; // setting the next pointer to the next words address
//else if (*str[i] = "\0") // FIXED: these can be deleted
// break;
tab_address[j] = NULL; // ADDED: setting the last element to NULL
return tab_address; // FIXED: you want to return the char** array not ptr
// free(tab_address); // FIXED: this is dead code, and you want to free it later anyway
}
int main(void)
{
char str[50] = "Hello There World";
char ** result = my_str_to_word_array(str);
char ** for_freeing = result; // save the start address of the result to later free it
while (*result != NULL)
{
printf("%s\n", *result);
result++;
}
free(for_freeing);
return 0;
}
Output
Hello There World
There World
World
Which is actually correct if you think about it.

I'm writing a shell in C and I am having trouble with pointers to char arrays in a struct

When I run my code the first printParams() call works perfectly. But every call after fork() the struct loses all of its char array values. I'm not that knowledgeable of pointers, but I can tell that the root of this problem is probably pointer-based. For example, the first printParams() will print out all of the values assigned in the Parse() function. But after the fork(), all of the integer values such as background and argumentCount are displayed but none of the string values associated with inputRedirect or the string values held in the vectorArguments array.
![Here is a photo of my output]]1
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include "parse.h"
void printParams(Param_t * param);
struct PARAM
{
char *inputRedirect; /* file name or NULL */
char *outputRedirect; /* file name or NULL */
int background; /* ethier 0 (false) or 1 (true) */
int argumentCount; /* number of tokens in argument vector
*/
char *argumentVector[MAXARGS]; /* array of String */
};
typedef struct PARAM Param_t;
int main(int argc, char *argv[]){
int i;
int debug;
pid_t pid;
if(argc>1){
if(!strcmp(argv[1], "-debug"))
debug = 1;
}
Param_t * testParam = Parse();
if(debug == 1){
printParams(testParam);
}
pid = fork();
printParams(testParam);
if(pid == 0){
exit(1);
}
return 0;
}
void printParams(Param_t *param)
{
int i;
printf("InputRedirect: [%s]\n", (param->inputRedirect != NULL) ? param-
>inputRedirect: "NULL");
printf("OutputRedirect: [%s]\n", (param->outputRedirect != NULL) ?
param->outputRedirect: "NULL");
printf ("Background: [%d]\n", param->background);
printf ("ArgumentCount: [%d]\n", param->argumentCount);
for (i = 0; i < param->argumentCount; i++)
printf("ArgumentVector[%2d]: [%s]\n", i, param->argumentVector[i]);
}
Param_t* Parse(){
char *toke[MAXARGS];
int i = 0;
char str[MAXSTRLENGTH];
int j;
int k=0;
Param_t* testParam = malloc(sizeof(Param_t));
testParam->argumentCount = 0;
printf("Enter your commands:\n");
fgets(str, MAXSTRLENGTH, stdin);
toke[i] = strtok(str, " ");
//Tokenizes the user input into the toke array
while(toke[i] != NULL){
//printf("%s\n", toke[i]);
++i;
toke[i] = strtok(NULL, " ");
}
i=0;
char c;
while(toke[i] != NULL){
c = toke[i][0];
if(c == '<')
{
for(j=0; j<strlen(toke[i]); ++j ){
toke[i][j] = toke[i][j+1];
}
testParam->inputRedirect = toke[i];
}
else if(c == '>')
{
for(j=0; j<strlen(toke[i]); ++j ){
toke[i][j] = toke[i][j+1];
}
testParam->outputRedirect = toke[i];
}
else if(c == '&')
{
testParam->background = 1;
//background
}
else
{
testParam->argumentVector[k] = toke[i];
k++;
//save as cmd vector
}
++i;
}
testParam->argumentCount = k;
return testParam;
}
The reason you loose all char * values is because strtok() function doesn't create buffer. Basically all your char* consist of an address pointing into str variable you read with fgets(). The str variable has scope only to end of Parse() function.
Solution for this:
Replace:
testParam->inputRedirect = toke[i];
with:
testParam->inputRedirect = malloc(MAXSTRLENGTH);
memset( testParam->inputRedirect, 0, MAXSTRLENGTH);
memcpy( testParam->inputRedirect, toke[i], strlen(toke[i]) );
But please note, that this leads to memory leak since there is no free().
Sugestion:
Create static instance of structure in main and give its pointer to Parse function.
Param_t testParam;
Parse( &testParam );
Let the Parse function fill it. And at the end of main call free for all char * buffers inside testParam

Concatenate a word n times

How can I do something like this?
x = abc
x^1 = abc
x^2 = abcabc
x^3 = abcabcabc
I tried using the strcat function inside a for loop, but it doesn't work.
int potw2;
char w2[100];
w2="abc";
potw2 = 5;
potenciarw2(w2, potw2);
void potenciarw2(char *pal, int potw2) {
for (int i = 0 ; i < potw2 ; i++) {
strcat(pal, pal);
}
printf("La palabra es:%s\n",pal);
}
strcat() expects the destination and source not to overlap. In other words, both parameters of strcat() cannot point to the same memory.
You need to allocate new memory for the resulting string, and use memcpy in a loop.
void potenciarw2(char *pal, int potw2)
{
size_t len = strlen(pal);
char* result = malloc(len * potw2 + 1); // allocate enough memory for the resulting string and null char
if (result == NULL) {
fputs("malloc() ha fallado", stdout);
return;
}
for (int i = 0 ; i < potw2 ; i++) {
memcpy(result + i * len, pal, len); // concatenate string using memcpy
}
result[len * potw2] = '\0'; // terminate with null char
printf("La palabra es:%s\n",result);
free(result);
}
Don't use strcat() for that, I mean for incremental concatenation of a string with known length, I can barely think of a situation where strcat() is really useful, there are some situations but generally this would work better, more efficiently for example
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *pow_string(const char *const source, int times)
{
size_t length;
char *result;
length = strlen(source);
result = malloc(length * times + 1);
if (result == NULL)
return NULL;
for (int index = 0 ; index < times ; ++index)
memcpy(result + index * length, source, length);
result[length * times] = '\0';
return result;
}
int
input_error()
{
fprintf(stderr, "error de entrada, ha introducido texto inválido\n");
return -1;
}
int
main(void)
{
char *result;
int power;
char word[100];
fprintf(stdout, "Ingrese un texto (máx 99 caracteres) > ");
if (scanf("%99[^\n]", word) != 1)
return input_error();
fprintf(stdout, "Cuántas veces quiere repetir la palabra ? ");
if (scanf("%d%*[ \t]", &power) != 1)
return input_error();
result = pow_string(word, power);
if (result == NULL)
return -1;
fprintf(stdout, "%s\n", result);
/* free `result' which was allocated with `malloc()' */
free(result);
return 0;
}
Your function needed a little bit of modification to work. Here's the modification:
void potenciarw2(char *pal, int potw2) {
/* allocate some memory and copy to it*/
char buffer[100];
strcpy(buffer,pal);
for (int i = 0 ; i < potw2 ; i++) {
strcat(buffer, pal);/*now you can use strcat() safely*/
}
/*copy data back to pal*/
strcpy(pal,buffer);
printf("La palabra es:%s\n",pal);
}
int main(void)
{
int potw2;
char w2[100] = "abc";
potw2 = 3;
potenciarw2(w2, potw2);
}

Showing line of text file without using strstr() in C

I have a problem with my C program. It's a command line argument of searching character string form the text file and output the line started with the user input character without using strstr(). It's OK but there is one problem. I want to output the whole file when Search Character is NULL. When I did this, the output become different of using strstr() build-in function. Can you help me what's wrong with my code, please?
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char* MyStrstr(char* pszSearchString, char* pszSearchWord);
int main(int argc, char* argv[])
{
char szTemp1[10] = {0};
char szTemp2[10] = {0};
char * pszTemp1 = NULL;
char * pszTemp2 = NULL;
strcpy(szTemp1, "aabaaacaaaad");
strcpy(szTemp2, "");
pszTemp1 = MyStrstr(szTemp1, szTemp2);
pszTemp2 = strstr(szTemp1, szTemp2);
printf("%s\n",pszTemp1);
printf("%s", pszTemp2);
return 0;
}
char* MyStrstr(char* pszSearchString, char* pszSearchWord) {
int nFcount = 0;
int nScount = 0;
int nSearchLen = 0;
int nIndex = 0;
char* pszDelString = NULL;
if(pszSearchString == NULL) {
return NULL;
}
if(pszSearchWord == ""){
return pszSearchString;
} else {
while(pszSearchWord[nSearchLen] != '\0') {
nSearchLen++;
}
for(nFcount = 0; pszSearchString[nFcount] != '\0'; nFcount++) {
if(pszSearchString[nFcount] == pszSearchWord[nScount]) {
nScount++;
} else {
nScount = 0;
}
if(nScount == nSearchLen) {
nIndex = (nFcount - nScount) + 1;
pszDelString = pszSearchString + nIndex;
}
return pszDelString;
}
}
return NULL;
}
Replace
if(pszSearchWord == "")
by
if (pszSearchWord[0] == 0)
pszSearchWord == "" compares the address pszSearchWord to the address of the string literal "" and those addresses are always different in your case. You cannot compare strings using the == operator.

Resources