I want to write a function to transform an array of n doubles to an string, a show function, something like:
struct vec { uint64_t n; double *x; };
char *show(struct vec *v) {...}
Notice that I don't want to print them, only do a serialization into a string.
How can I do this in C?
You can do something like this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#define MAX_DOUBLE_LENGTH 15
typedef struct
{
size_t n;
double* x;
} DoubleArray;
int ShowArray(const DoubleArray* const doubleArrayPtr, char** const resultStringPtr)
{
int errorCode = 0;
char* tempStr = NULL;
char str[MAX_DOUBLE_LENGTH + 2]; /* 1 for trailing space and 1 for null-terminator */
size_t N = 0;
size_t i = 0;
if (doubleArrayPtr == NULL || resultStringPtr == NULL)
{
errorCode = 1;
}
else
{
if (doubleArrayPtr->n != 0)
{
/*
calculating max string length from:
str = <double01> <space> <double02> <space> <double03> <null-terminator>
ex.: str = '3.25 4.75 0.01 5.678\0'
*/
N = doubleArrayPtr->n * MAX_DOUBLE_LENGTH + doubleArrayPtr->n;
tempStr = malloc(N * sizeof(*tempStr));
if (tempStr == NULL)
{
errorCode = 1;
}
else
{
memset(tempStr, 0, N * sizeof(*tempStr));
for(i = 0; i < doubleArrayPtr->n; i++)
{
sprintf(str, "%.6f ", doubleArrayPtr->x[i]);
strcat(tempStr, str);
}
tempStr[strlen(tempStr) - 1] = '\0';
/* string formed -- allocating buffer for result */
(*resultStringPtr) = malloc((strlen(tempStr) + 1) * sizeof(**resultStringPtr));
if ((*resultStringPtr) == NULL)
{
errorCode = 1;
}
else
{
/* exporting result */
memcpy((*resultStringPtr), tempStr, strlen(tempStr) * sizeof(*tempStr));
(*resultStringPtr)[strlen(tempStr)] = '\0';
}
}
free(tempStr);
tempStr = NULL;
}
}
return errorCode;
}
int main(void)
{
/* test code part */
DoubleArray d;
char* s = NULL;
size_t i = 0;
srand(time(NULL));
d.n = rand() % 21;
d.x = malloc(d.n * sizeof(*d.x));
for(i = 0; i < d.n; i++)
{
d.x[i] = (rand() % 99999) / 100.0;
printf("[%d] = %f\n", i, d.x[i]);
}
ShowArray(&d, &s);
printf("str = '%s'\n", s);
free(d.x);
free(s);
return 0;
}
Related
I attempt to malloc char** to store string, and free this, but I got this error. I can't understand why. The steps are as follows:
1:
char **pid_array = (char **)malloc(sizeof(char *) * MAX_LEN);
2:
pid_array[0] = (char *)malloc(sizeof(char) * SINGLE_LEN * MAX_LEN);
3:
free(pid_array); free(pid_array[0]);
The detailed code follows:
#include <assert.h>
#include <ctype.h>
#include <dirent.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#define MAX_LEN 1000
#define SINGLE_LEN 10
int isPid(char *str) {
int len = strlen(str);
for (int i = 0; i < len; i++) {
if (isdigit(str[i]) == 0) {
return 1;
}
}
return 0;
}
void getFileName(char *dir_path, char *pid_array[], int *len) {
DIR *dir = opendir(dir_path);
if (dir == NULL) {
fprintf(stderr, "path open failed!\n");
exit(EXIT_FAILURE);
}
chdir(dir_path);
struct dirent *ent;
int i = 0;
while ((ent = readdir(dir)) != NULL) {
if (strcmp(ent->d_name, ".") == 0 || strcmp(ent->d_name, "..") == 0) {
continue;
}
int size = strlen(ent->d_name);
if (isPid(ent->d_name) == 0) {
pid_array[i++] = ent->d_name;
}
}
*len = i;
closedir(dir);
}
int main(int argc, char *argv[]) {
int pflag, nflag, vflag;
pflag = 0;
nflag = 0;
vflag = 0;
int opt;
while ((opt = getopt(argc, argv, "pvn")) != -1) {
switch (opt) {
case 'p':
pflag = 1;
break;
case 'v':
vflag = 1;
break;
case 'n':
nflag = 1;
break;
}
}
printf("pflag=%d; nflag=%d; vflag=%d; optind=%d\n", pflag, nflag, vflag, optind);
char **pid_array = (char **)malloc(sizeof(char *) * MAX_LEN);
pid_array[0] = (char *)malloc(sizeof(char) * SINGLE_LEN * MAX_LEN);
for(int i=0; i < MAX_LEN; i++){
pid_array[i]=pid_array[i-1]+SINGLE_LEN;
}
/*
for (int i = 0; i < MAX_LEN; i++) {
pid_array[i] = (char *)malloc(sizeof(char) * SINGLE_LEN);
assert(pid_array[i] != NULL);
}
*/
for (int i = 0; i < MAX_LEN; i++) {
free(pid_array[i]);
}
int *pid_array_len = (int *)malloc(sizeof(int));
getFileName("/proc", pid_array, pid_array_len);
for (int i = 0; i < *pid_array_len; i++) {
printf("%d\n", atoi(pid_array[i]));
}
free(pid_array);
free(pid_array[0]);
free(pid_array_len);
return 0;
}
The error is follow:
error
The steps as noted are not correct.
if pid_array is char** then
*pid_array is char*
**pid_array is char
And you need to construct them as such. And free them in the reverse order. If you intend to have a vector of pointers at pid_array then your case is very very common: every C program gets one for free. The main prototype can be declared as
int main(int argc, char**argv);
The system knows how many char* to pass to the program, but in your case maybe the simplest (safest) way is to use encapsulation and build a block like this
typedef struct
{
size_t argc;
char** argv;
} Block;
I will let an example below.
a way to free the block properly
If you insist in using just the pointer you can easily adapt this. Anyway a possible implementation is
Block* delete (Block* blk)
{
if (blk == NULL) return NULL;
fprintf(
stderr, "Deleting block of %llu strings\n",
blk->argc);
for (int i = 0; i < blk->argc; i += 1)
free(blk->argv[i]);
free(blk->argv);
free(blk);
fprintf(stderr, "Deleted...\n");
return NULL;
}
The reason to return a pointer is to create a simple way to assure the pointer is invalidated as in
my_block = delete (my_block);
In the example
A block is created
is filled with strings of random size
the strings are printed
the block is deleted
main for the example
int main(void)
{
srand(220630);
const int size = MAX_LEN;
Block* my_block = build(size);
fill(my_block);
show(my_block, "a vector of numbered strings");
my_block = delete (my_block);
return 0;
}
the output
a vector of numbered strings
25 strings:
1 "#000#k"
2 "#001#swfsxji"
3 "#002#cn"
4 "#003#akmxhksqgb"
5 "#004#dqnegzryobmhucldx"
6 "#005#iiuqddvuvukkrs"
7 "#006#jxvlsolocgnvgjcrwh"
8 "#007#zylbzumyhmeswxuno"
9 "#008#ex"
10 "#009#ixinxqyxqydnswb"
11 "#010#ylxelydzqgs"
12 "#011#absdfpdjvgwhxcmzekr"
13 "#012#sceqzvmjskkrmszpth"
14 "#013#n"
15 "#014#rsmkrqhssjniqgphjp"
16 "#015#dgojvpflydevwudvv"
17 "#016#qbmaolgrskkqghhkgb"
18 "#017#uzsunopqpdawg"
19 "#018#rvdeaiooylywf"
20 "#019#zfejmgqxu"
21 "#020#fjubcmllylxqahvbfh"
22 "#021#zwanyivra"
23 "#022#vooropiugmuya"
24 "#023#js"
25 "#024#qzecia"
Deleting block of 25 strings
Deleted...
The complete C code
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_LEN 25
typedef struct
{
size_t argc;
char** argv;
} Block;
Block* build(size_t ttl);
Block* delete (Block* blk);
int fill(Block* bl);
int show(Block* blk, const char* title);
int main(void)
{
srand(220630);
const int size = MAX_LEN;
Block* my_block = build(size);
fill(my_block);
show(my_block, "a vector of numbered strings");
my_block = delete (my_block);
return 0;
}
Block* build(size_t ttl)
{
if (ttl == 0) return NULL;
Block* blk = (Block*)malloc(sizeof(Block));
if (blk == NULL) return NULL;
blk->argc = (ttl > MAX_LEN) ? MAX_LEN : ttl;
blk->argv = (char**)malloc(ttl * sizeof(char*));
if (blk->argv == NULL) return NULL;
for (int i = 0; i < ttl; i += 1)
*(blk->argv + i) = NULL;
return blk;
}
int fill(Block* bl)
{
const char prefix[] = "#nnn#"; // common prefix
char buffer[30] = {0};
char data[20] = {0};
for (int i = 0; i < bl->argc; i += 1)
{
int rest = 1 + rand() % 19;
for (int j = 0; j < rest; j += 1)
data[j] = 'a' + rand() % 26; // a single letter
data[rest] = 0; // terminates string
int res = sprintf(buffer, "#%03d#%s", i, data);
bl->argv[i] = (char*)malloc(strlen(buffer) + 1);
strcpy(bl->argv[i], buffer);
}
return 0;
}
int show(Block* blk, const char* title)
{
if (title != NULL) printf("%s\n", title);
printf("%llu strings:\n", blk->argc);
for (int i = 0; i < MAX_LEN; i += 1)
printf("%d\t \"%s\"\n", 1 + i, *(blk->argv + i));
printf("\n");
return 0;
}
Block* delete (Block* blk)
{
if (blk == NULL) return NULL;
fprintf(
stderr, "Deleting block of %llu strings\n",
blk->argc);
for (int i = 0; i < blk->argc; i += 1)
free(blk->argv[i]);
free(blk->argv);
free(blk);
fprintf(stderr, "Deleted...\n");
return NULL;
}
// https://stackoverflow.com/questions/72809939/
// how-do-i-use-free-properly-to-free-memory-when
// -using-malloc-for-char
link of program question https://www.hackerrank.com/challenges/cut-the-sticks/problem
#include <assert.h>
#include <limits.h>
#include <math.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char* readline();
char** split_string(char*);
int* cutTheSticks(int arr_count, int* arr, int* result_count) {
int c=arr_count,min;
int result[c];
for (int k=0;k<arr_count;k++){
min = *arr;
for (int i = 0; i < c; i++) {
if (*(arr + i) < min)
min = *(arr + i);
}
int count=0;
for (int i=0; i < c; i++) {
if(min==*(arr+i))count++;
}
for (int i=0; i < c; i++) {
*(arr+i)=*(arr+i)-min;
}
int temp=0;
for(int i=0;i<c;i++){
for(int x=i;x<c;x++){
if(*(arr+i)<*(arr+x)){
temp=*(arr+i);
*(arr+i)=*(arr+x);
*(arr+x)=temp;
}
}
}
result[k]= c;
*(result_count)=*(result_count)+1;
c = c - count;
if(c==0)break;
}
return result;
}
int main()
{
FILE* fptr = fopen(getenv("OUTPUT_PATH"), "w");
char* n_endptr;
char* n_str = readline();
int n = strtol(n_str, &n_endptr, 10);
if (n_endptr == n_str || *n_endptr != '\0') { exit(EXIT_FAILURE); }
char** arr_temp = split_string(readline());
int* arr = malloc(n * sizeof(int));
for (int i = 0; i < n; i++) {
char* arr_item_endptr;
char* arr_item_str = *(arr_temp + i);
int arr_item = strtol(arr_item_str, &arr_item_endptr, 10);
if (arr_item_endptr == arr_item_str || *arr_item_endptr != '\0') {
exit(EXIT_FAILURE); }
*(arr + i) = arr_item;
}
int arr_count = n;
int result_count;
int* result = cutTheSticks(arr_count, arr, &result_count);
for (int i = 0; i < result_count; i++) {
fprintf(fptr, "%d", *(result + i));
if (i != result_count - 1) {
fprintf(fptr, "\n");
}
}
fprintf(fptr, "\n");
fclose(fptr);
return 0;
}
char* readline() {
size_t alloc_length = 1024;
size_t data_length = 0;
char* data = malloc(alloc_length);
while (true) {
char* cursor = data + data_length;
char* line = fgets(cursor, alloc_length - data_length, stdin);
if (!line) { break; }
data_length += strlen(cursor);
if (data_length < alloc_length - 1 || data[data_length - 1] == '\n') {
break; }
size_t new_length = alloc_length << 1;
data = realloc(data, new_length);
if (!data) { break; }
alloc_length = new_length;
}
if (data[data_length - 1] == '\n') {
data[data_length - 1] = '\0';
}
data = realloc(data, data_length);
return data;
}
char** split_string(char* str) {
char** splits = NULL;
char* token = strtok(str, " ");
int spaces = 0;
while (token) {
splits = realloc(splits, sizeof(char*) * ++spaces);
if (!splits) {
return splits;
}
splits[spaces - 1] = token;
token = strtok(NULL, " ");
}
return splits;
}
This above code is my full code from harkerrank, below is main fuction.
i can't able to return my pointer value from cutTheStricks to main function.
// Please store the size of the integer array to be returned in
result_count
pointer. For example,
// int a[3] = {1, 2, 3};
//
// *result_count = 3;
//
// return a;
int* cutTheSticks(int arr_count, int* arr, int* result_count) {
int c=arr_count,min;
int result[c];
for (int k=0;k<arr_count;k++){
min = *arr;
for (int i = 0; i < c; i++) {
if (*(arr + i) < min)
min = *(arr + i);
}
int count=0;
for (int i=0; i < c; i++) {
if(min==*(arr+i))count++;
}
for (int i=0; i < c; i++) {
*(arr+i)=*(arr+i)-min;
}
int temp=0;
for(int i=0;i<c;i++){
for(int x=i;x<c;x++){
if(*(arr+i)<*(arr+x)){
temp=*(arr+i);
*(arr+i)=*(arr+x);
*(arr+x)=temp;
}
}
}
result[k]= c;
*(result_count)=*(result_count)+1;
c = c - count;
if(c==0)break;
}
return result;
}
I am not getting any output but my logic is correct.
I know there is there is something missing therefore i can't able to return my output;
I can't figure out which pointer value(*result or *result_count ) is not passing
or what is happening i can't able to figure out.
You are returning the address of a local array whose life time ends with the function, change
int result[c];
to
int *result = malloc(sizeof(*result) * c);
You are also using the address of an uninitialized value here:
*(result_count)=*(result_count)+1;
change
int result_count;
to
int result_count = 0;
The point of the program is to replace every succession of 2 or more vocals with my name.
How can I make that reallocation successful?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void main() {
char vocale[] = "AEIOUaeiou",
sir[] = "Aana are muaulte meiree.";
char *src = (char*)malloc(strlen(sir) + 1);
src = sir;
char name[] = "Marian";
int count = 0,
i = 0;
while (i < strlen(src)) {
if (strchr(vocale, src[i])) {
count++;
i++;
}
else {
if (count >= 2) {
src = (char*)realloc(src, strlen(src) + strlen(name) + 1);
insereaza(src, count, name, i);
i = i + strlen(name);
count = 0;
}
else {
count = 0;
i++;
}
}
}
puts(src);
_getch();
}
here is a proposal with some changes, it is difficult because I don't know what insereaza does
void main() {
const char * vocale = "AEIOUaeiou";
char * src = strdup("Aana are muaulte meiree."); /* must be in the heap for realloc */
const char * name = "Marian";
int srcLen = strlen(src);
int nameLen = strlen(name);
int count = 0, i = 0;
while (i < srcLen) {
if (strchr(vocale, src[i])) {
count++;
i++;
}
else {
if (count >= 2) {
src = (char*) realloc(src, srcLen + nameLen + 1); /* perhaps too large */
insereaza(src, count, name, i);
srcLen += nameLen; /* or srcLen += nameLen - count + 1 ? */
i += nameLen; /* or i += nameLen - count + 1 ? */
}
else {
i++;
}
count = 0;
}
}
puts(src);
_getch();
}
I'm trying to create a program which returns the Longest repeated substring. I've almost got the solution, but for some reason my strcmp gives an error when he is busy to find the LRS. Could someone explain me why there is an error and how I solve this?
The code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define NSTRINGS 4
char* searchLongestRepeatedSubstring(char* string);
char** makeSuffixArray(char* string);
void freeSuffixArray(char** suffixArray);
int cmp(const void*a, const void* b);
/* do not change this code */
int main(void)
{
char* strings[NSTRINGS] = {
"bananas",
"ask not what your country can do for you, but what you can do for your country",
"main",
"" };
char* result;
for (int i = 0; i < NSTRINGS; ++i)
{
result = searchLongestRepeatedSubstring(strings[i]);
if (result != NULL)
{
/* write out LRS */
printf("%s: \"%s\"\n", strings[i], result);
/* free() the result */
free(result);
result = NULL;
}
else
printf("Geen longest repeated substring.\n");
}
return 0;
}
/**
* Finds the LRS from a string using the function makeSuffixArray
*
* #param the given string
* #return the longest repeated substring
*/
char* searchLongestRepeatedSubstring(char* string)
{
char **p;
p = makeSuffixArray(string);
size_t length = strlen(string);
int max_sz = 0;
char max_word;
int curr_sz = 0;
int curr_word;
char* word1;
char* word2;
char s1, s2;
size_t length1;
size_t length2;
for (size_t i = 0; i < length; i++)
{
for (size_t j = i + 1; j < length; j++)
{
word1 = p[i];
word2 = p[j];
length1 = strlen(word1);
length2 = strlen(word1);
for (size_t x = 0; x < length1; x++)
{
s1 = word1[x];
for (size_t y = 0; y < length2; y++)
{
s2 = word2[y];
if (strcmp(s1, s2) == 0) {
curr_sz++;
strcat(curr_word, s1);
x++;
}
else
break;
}
}
if (curr_sz > max_sz) {
max_sz = curr_sz;
curr_sz = 0;
max_word = curr_word;
curr_word = "";
}
else {
curr_sz = 0;
curr_word = "";
}
}
}
return max_word;
}
/**
* Creates the suffix array of the given string
*
* #param the given string
* #return the suffix array
*/
char** makeSuffixArray(char* string)
{
size_t length = strlen(string);
char **p = (char**)malloc(length * sizeof(char*));
for (size_t i = 0; i < strlen(string); i++)
{
p[i] = &string[i];
puts(p[i]);
}
qsort(p, length, sizeof(char*), cmp);
return p;
}
int cmp(const void* a, const void* b)
{
char ** p = (char**)a;
char ** t = (char**)b;
return strcmp(*p, *t);
}
/**
* free() the memory allocated for the suffix array
*
* #param the given suffix array
*/
void freeSuffixArray(char** suffixArray)
{
free(suffixArray);
}
In your function char* searchLongestRepeatedSubstring-
if (strcmp(s1, s2) == 0) {
s1 and s2 are both char variables , and you pass them to strcmp which expects const char * as arguments , therefore, your compiler complaints .
You can compare them like this-
if(s1==s2)
Also this statement in same if block -
strcat(curr_word, s1);
instead you can do this -
size_t len=strlen(curr_word);
curr_word[len]=s1; // make sure curr_word is large enough
curr_word[len+1]='\0';
I have some program which decompress some string which is already mentioned here: How to decompres array of char in c. After I finished it I have problem with function free (without it, it works ok). There is some strange behaviour and the last assert fails because of : Aborted; core dumped;
when I debug this program I found that problem is in this cycle:
for (j = 0; j < max - 1; j++) {
vysledek[index] = src[i - pom];
printf("cccc%d\n%s\n", j,vysledek);
printf("xxx%c", src[i - pom]);
index++;
}
it prints:
...
xxx#cccc19
HHeeeeeellllllllooooooooooooooo#####################�
xxx#cccc20
HHeeeeeellllllllooooooooooooooo######################
xxx#cccc21
HHeeeeeellllllllooooooooooooooo#######################
xxx#cccc22
HHeeeeeellllllllooooooooooooooo########################
xxx#cccc23
HHeeeeeellllllllooooooooooooooo#########################Hello______________________________world!
xxx#cccc24
HHeeeeeellllllllooooooooooooooo##########################ello______________________________world!
...
can someone explain me this ? How can Hello world from second assert discover in third one ?
whole program is here:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <assert.h>
char * decompress(const char * src) {
int max = 0;
int pom = 1;
int maxSize = 0;
int index = 0;
int isNumber = 0;
int i;
for (i = 0; src[i] != 0; i++) {
max = 0;
isNumber = 0;
while (isdigit(src[i])) {
int digit = (src[i] - '0');
max = max * 10 + digit;
i++;
isNumber = 1;
}
if (max == 0 && !isNumber) {
max = 1;
}
maxSize = maxSize + max;
}
char *vysledek = (char*) malloc((maxSize) * sizeof (int));
for (i = 0; src[i] != 0; i++) {
max = 0;
pom = 0;
isNumber = 0;
while (isdigit(src[i])) {
int digit = (src[i] - '0');
max = max * 10 + digit;
i++;
pom++;
isNumber = 1;
}
if (!isNumber) {
vysledek[index] = src[i];
//printf("%c", src[i]);
index++;
} else {
i--;
int j;
if (max < 1) {
index--;
}
for (j = 0; j < max - 1; j++) {
vysledek[index] = src[i - pom];
//printf("cccc%d\n%s\n", j,vysledek);
//printf("xxx%c", src[i - pom]);
index++;
}
}
//printf("\n%d\n", index);
}
return vysledek;
}
int main(int argc, char * argv []) {
char * res;
assert(!strcmp(
(res = decompress("Hello world!")),
"Hello world!"));
//free(res);
assert(!strcmp(
(res = decompress("Hello_30world!")),
"Hello______________________________world!"));
//free(res);
assert(!strcmp(
(res = decompress("H2e6l8o15 35w5o6r-2d0!!")),
"HHeeeeeellllllllooooooooooooooo wwwwwoooooor--!!"));
//free(res);
return 0;
}
The problem is, that you compare a null-terminated string with a not-null-terminated string.
In your function decompress() you need to reserve one more int and add the missing \0 to the copied buffer.
char *vysledek = (char*) malloc((maxSize) * sizeof (int) + sizeof(int));
[...]
vysledek[index] = '\0';