C: Loop through struct and concat to string - c

I have C program with the following struct:
struct {
char *ext;
char *filetype;
} extensions [] = {
{"gif", "image/gif" },
{"jpg", "image/jpg" },
{"jpeg","image/jpeg"},
{"png", "image/png" },
{0,0}
};
How do I create a function that returns a string that contains only the extensions separated by new lines? Basically this is what to be able to do this:
printf("\nThe following extensions are supported:\n%s",GetExtensions());
And have it output this:
The following extensions are supported:
.gif
.jpg
.jpeg
.png
I think I've got the looping part correct, but I'm not understanding how to concat each ext + \n to a string:
#include <leaving these off for brevity...>
struct {
char *ext;
char *filetype;
} extensions [] = {
{"gif", "image/gif" },
{"jpg", "image/jpg" },
{"jpeg","image/jpeg"},
{"png", "image/png" },
{0,0}
};
char *getExtensions(void) {
char* exts;
int i;
for(i=0;extensions[i].ext != 0;i++){
// What do I do here??
}
return exts;
}
int main(int argc, char **argv){
printf("\nThe following extensions are supported: \n%s",GetExtensions());
}

It seems you mean the following.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct extension
{
char *ext;
char *filetype;
};
char * getExtensions( const struct extension a[] )
{
size_t n = 0;
for ( size_t i = 0; a[i].ext != NULL; i++ )
{
n += strlen( a[i].ext ) + 1;
}
char *s = malloc( n + 1 );
if ( s != NULL )
{
s[0] = '\0';
for ( size_t i = 0; a[i].ext != NULL; i++ )
{
strcat( s, a[i].ext );
strcat( s, "\n" );
}
}
return s;
}
int main(void)
{
struct extension extensions [] =
{
{"gif", "image/gif" },
{"jpg", "image/jpg" },
{"jpeg","image/jpeg"},
{"png", "image/png" },
{ NULL, NULL }
};
char *s = getExtensions( extensions );
printf( "The following extensions are supported:\n%s", s );
free( s );
return 0;
}
The program output is
The following extensions are supported:
gif
jpg
jpeg
png

#include <stdio.h>
#include <string.h>
// Your struct
struct extensionInfo {
char *ext;
char *filetype;
};
struct extensionInfo extensions [] = {
{"gif", "image/gif" },
{"jpg", "image/jpg" },
{"jpeg","image/jpeg"},
{"png", "image/png" },
{0,0}
};
int main(int argc, char **args, char **env) {
char buffer[1024];
struct extensionInfo *ext;
// Initialize the buffer
memset(buffer, 0, sizeof(buffer));
// Insert your first text.
strncat(buffer, "The following extensions are supported:", sizeof(buffer) - 1);
// Loop through your array and append everything
for (ext = extensions; ext->ext != 0; ext++) {
strncat(buffer, "\n", sizeof(buffer) - 1);
strncat(buffer, ext->ext, sizeof(buffer) - 1);
}
// Show your result
printf("%s\n", buffer);
return 0;
}
Here is a commented example which works. If you have any questions, feel free to ask.

I think the following is what you wish. You can read the comments to grasp how it works.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct {
char *ext;
char *filetype;
} extensions [] = {
{"gif", "image/gif" },
{"jpg", "image/jpg" },
{"jpeg","image/jpeg"},
{"png", "image/png" },
{0,0}
};
char *getExtensions(void) {
size_t count = 0;
// let's know how many characters are needed for all extensions
for(int i = 0; extensions[i].ext != 0; ++i) {
size_t j = 0;
for (; extensions[i].ext[j] != 0; ++j) ;
count += j + 1; // +1 for every newline
}
// +1 for null terminator
char *str = calloc(count + 1, sizeof(char));
// let's concatenate
for(size_t i = 0; extensions[i].ext != 0; ++i) {
strcat(str, extensions[i].ext);
strcat(str, "\n");
}
return str;
}
int main(int argc, char **argv){
char * const result = getExtensions();
printf("\nThe following extensions are supported: \n%s", result);
free(result);
}

Related

How remove fragment from string

how remove fragment from string in c?
For example:
int main()
{
char *string = "Qwertyuio pasdf ghjklzxcv bnm";
char *fragment = "pasdf";
}
How cut pasdf but save other?
In your example, you cannot change the content of string.
Here's how to do it properly:
#include <stdio.h>
#include <string.h>
int
main()
{
char *string = strdup("Qwertyuio |pasdf| ghjklzxcv bnm");
char *fragment = "pasdf";
char *w = string;
int length = strlen(string);
printf("%s\n", string);
while (*w)
{
if (!strncmp(w, fragment, strlen(fragment)))
{
length -= strlen(fragment);
memmove(w, w + strlen(fragment), length);
}
else
{
w++;
length--;
}
}
*w = 0;
printf("%s\n", string);
free(string);
return 0;
}

Generate array of all html entities

I have a program where i need to escape all html entities in a string. I have array of entity=>substitute pairs and function that does search and replace. It would be very hard to write all possible entities to array by hand. How could i generate array of all possible entities with their substitutes?
Here is the function i have in use currently:
static char *replacehtmlentities(char *str) {
int i;
char *tmp = NULL;
char *tmp2 = str;
struct entity {
char *entity;
char *substitute;
} entities[] = {
{ " ", " " },
{ "&excl;", "!" },
{ "&quest;", "?" },
{ "&", "&" },
{ "&num;", "#" },
{ """, "\"" },
{ "&apos;", "'" },
{ "'", "'" },
{ NULL, NULL },
};
for (i = 0; entities[i].entity; i++) {
tmp = replace_str2(tmp2, entities[i].entity, entities[i].substitute);
if (i)
free(tmp2);
tmp2 = tmp;
}
return tmp2;
}
I wrote program "genentities" that reads html entities online from http://www.w3.org/html/wg/drafts/html/master/entities.json and outputs C header with structure containing all entities with substitutes.
Here is the final program:
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <stddef.h>
#include <jansson.h>
#include <curl/curl.h>
#define BUFFER_SIZE (1024 * 1024) /* 1024 KB */
char *url = "http://www.w3.org/html/wg/drafts/html/master/entities.json";
void eprintf(const char *fmt, ...) {
va_list ap;
va_start(ap, fmt);
vfprintf(stderr, fmt, ap);
va_end(ap);
exit(EXIT_FAILURE);
}
struct write_result {
char *data;
int pos;
};
static size_t write_response(void *ptr, size_t size, size_t nmemb, void *stream) {
struct write_result *result = (struct write_result *)stream;
if(result->pos + size * nmemb >= BUFFER_SIZE - 1)
eprintf("error: too small buffer\n");
memcpy(result->data + result->pos, ptr, size * nmemb);
result->pos += size * nmemb;
return size * nmemb;
}
static char *request(const char *url) {
CURL *curl;
CURLcode status;
char *data;
long code;
curl = curl_easy_init();
data = malloc(BUFFER_SIZE);
if (!curl || !data)
return NULL;
struct write_result write_result = {
.data = data,
.pos = 0
};
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_response);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &write_result);
status = curl_easy_perform(curl);
if (status != 0)
eprintf("error: unable to request data from %s:\n"
"%s\n", url, curl_easy_strerror(status));
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &code);
if(code != 200)
eprintf("error: server responded with code %ld\n", code);
curl_easy_cleanup(curl);
curl_global_cleanup();
data[write_result.pos] = '\0';
return data;
}
static char *replace_str2(const char *str, const char *old, const char *new) {
char *ret, *r;
const char *p, *q;
size_t oldlen = strlen(old);
size_t count, retlen, newlen = strlen(new);
int samesize = (oldlen == newlen);
if (!samesize) {
for (count = 0, p = str; (q = strstr(p, old)) != NULL; p = q + oldlen)
count++;
/* This is undefined if p - str > PTRDIFF_MAX */
retlen = p - str + strlen(p) + count * (newlen - oldlen);
} else
retlen = strlen(str);
if ((ret = malloc(retlen + 1)) == NULL)
return NULL;
r = ret, p = str;
while (1) {
/* If the old and new strings are different lengths - in other
* * words we have already iterated through with strstr above,
* * and thus we know how many times we need to call it - then we
* * can avoid the final (potentially lengthy) call to strstr,
* * which we already know is going to return NULL, by
* * decrementing and checking count.
* */
if (!samesize && !count--)
break;
/* Otherwise i.e. when the old and new strings are the same
* * length, and we don't know how many times to call strstr,
* * we must check for a NULL return here (we check it in any
* * event, to avoid further conditions, and because there's
* * no harm done with the check even when the old and new
* * strings are different lengths).
* */
if ((q = strstr(p, old)) == NULL)
break;
/* This is undefined if q - p > PTRDIFF_MAX */
ptrdiff_t l = q - p;
memcpy(r, p, l);
r += l;
memcpy(r, new, newlen);
r += newlen;
p = q + oldlen;
}
strcpy(r, p);
return ret;
}
char *escapeformatspecifiers(const char *src) {
int i;
char *tmp = NULL;
char *tmp2 = src;
struct formatspecifiers {
char *specifier;
char *substitute;
} fspecs[] = {
{ "\\", "\\\\" },
{ "\"", "\\\"" },
{ "\n", "\\n" },
{ NULL, NULL },
};
for (i = 0; fspecs[i].specifier; i++) {
tmp = replace_str2(tmp2, fspecs[i].specifier, fspecs[i].substitute);
if (i)
free(tmp2);
tmp2 = tmp;
}
return tmp2;
}
int main(void) {
char *text;
const char *key;
size_t index;
json_t *root;
json_t *value;
json_t *arrvalue;
json_t *characters, *codepoints;
json_error_t error;
char *chartmp;
text = request(url);
if(!text)
return 1;
root = json_loads(text, 0, &error);
free(text);
if (!root)
eprintf("error: on line %d: %s\n", error.line, error.text);
if (!json_is_object(root))
eprintf("error: root is not an object\n");
puts("#ifndef HTMLENTITIES_H");
puts("#define HTMLENTITIES_H\n");
puts("struct entity {");
puts("\tchar *entity;");
puts("\tchar *substitute;");
puts("} entities[] = {");
json_object_foreach(root, key, value) {
characters = json_object_get(value, "characters");
codepoints = json_object_get(value, "codepoints");
if(!json_is_array(codepoints))
puts("not an array");
chartmp = escapeformatspecifiers(json_string_value(characters));
printf("\t{ \"%s\", \"%s\" },\n", key, chartmp);
json_array_foreach(codepoints, index, arrvalue) {
printf("\t{ \"&#%.0f;\", \"%s\" },\n", json_number_value(arrvalue), chartmp);
}
free(chartmp);
}
puts("\t{ NULL, NULL },");
puts("};\n");
puts("#endif");
json_decref(root);
return 0;
}
this method of writing a struct:
struct entity
{
char *entity;
char *substitute;
} entities[] = {
{ " ", " " },
{ "&excl;", "!" },
{ "&quest;", "?" },
{ "&", "&" },
{ "&num;", "#" },
{ """, "\"" },
{ "&apos;", "'" },
{ "'", "'" },
{ NULL, NULL },
};
is depreciated (and many debuggers will not display the individual fields).
this is the correct/preferred method:
struct entity_t
{
char *entity;
char *substitute;
};
struct entity_t entities[] =
{
{ " ", " " },
{ "&excl;", "!" },
{ "&quest;", "?" },
{ "&", "&" },
{ "&num;", "#" },
{ """, "\"" },
{ "&apos;", "'" },
{ "'", "'" },
{ NULL, NULL },
};
where I used 'entity_t' to differentiate the struct declaration from
the field within the struct
also, if not compling 'strict ansi', the final ',' is not needed

changing size of array

I have the following code:
typedef struct my_data {
char* name;
}my_data;
my_data data[]={
{ .name = "Peter" },
{ .name = "James" },
{ .name = "John" },
{ .name = "Mike" }
};
void loaddata()
{
FILE * in;
if((in = fopen("data.txt","rt")) != NULL) {
memset(data, 0, sizeof(data));
int i = 0;
while(!feof(in))
{
fscanf(in,"%s", &data[i].name);
i++;
};
fclose(in);
}
}
to read contents and process them I use this:
for (i=0; i<sizeof(data)/sizeof(data[0]); i++)
but if the number of lines in file is less than the number of defined array I get a lot of empty records so I modified it into:
for (i=0; (i<sizeof(data)/sizeof(data[0])) && strlen(data[i].name)>0; i++)
which is working fine but I'm sure I will get errors if the number of lines in file will be larger than the defined array size.
Any idea how to make this code safe? To change array dynamically?
EDIT:
this way is working with size 300
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
typedef struct my_data {
char name[100];
}my_data;
struct my_data data[300];
my_data data_arr[]={
{ .name = "Peter" },
{ .name = "James" },
{ .name = "John" },
{ .name = "Mike" }
};
void process_data()
{
char name[100];
int i;
for (i=0; (i<sizeof(data)/sizeof(data[0])) && strlen(data[i].name)>0; i++) {
sprintf(name, "%s", data[i].name);
printf("%s\n", name);
}
}
void load_data()
{
int i = 0;
FILE * in;
if((in = fopen("data.txt","rt")) != NULL) {
while(!feof(in))
{
fscanf(in,"%s", &data[i].name);
i++;
};
fclose(in);
}
else
{
for (i=0; (i<sizeof(data_arr)/sizeof(data_arr[0])) && strlen(data_arr[i].name)>0; i++) {
sprintf(data[i].name, "%s", data_arr[i].name);
}
}
return;
}
int main()
{
load_data();
process_data();
return 0;
}
Arrays do not grow dynamically in C. So you have a few approaches:
get a pointer to a block of memory (using malloc) and use realloc whenever you need more space for an array - and index into your pointer
create a linked list using malloc for every new item you want to add to your list
Don't forget when using malloc to call free on every single block that you called malloc for.

The Notorious Dynamic allocation of pointers to arrays of structures

I've a long version of a program that uses this code and a short version. This is the short version and oddly, this code runs perfectly fine in short version program, but because I get an access violation in the larger version, I get the feeling something is wrong. Does anyone see anything terribly wrong (that might lead to data corruption and/or access violation errors) with the following code? Or is this alright?
char strlist[5][11] = {
{ "file01.txt" },
{ "file02.txt" },
{ "file03.txt" },
{ "file04.txt" },
{ "file05.txt" }
};
typedef struct DYNAMEM_DATA {
char *string;
int strlen;
} DYNAMEM_DATA;
typedef struct DYNAMEM_STRUCT {
struct DYNAMEM_DATA **data;
int num_elements;
} DYNAMEM_STRUCT;
DYNAMEM_STRUCT *create_dynamem_struct(int num_elements, char *strlist)
{
DYNAMEM_STRUCT *ds = (DYNAMEM_STRUCT *)calloc(1, sizeof(DYNAMEM_STRUCT));
wchar_t wstring[128];
char len[3];
int i;
ds->data = (DYNAMEM_DATA **)calloc(num_elements, sizeof(DYNAMEM_DATA *));
ds->num_elements = num_elements;
for(i = 0; i < num_elements; i++) {
ds->data[i] = (DYNAMEM_DATA *)calloc(1, sizeof(DYNAMEM_DATA));
ds->data[i]->string = (char *)calloc(1, strlen(&strlist[i*11])+5);
ds->data[i]->strlen = strlen(&strlist[i*11]);
sprintf(ds->data[i]->string, "%s, %d", &strlist[i*11], ds->data[i]->strlen);
mbstowcs(wstring, ds->data[i]->string, 128);
MessageBox(NULL, wstring, TEXT("Error"), MB_OK);
}
return ds;
}
This code runs, produces 5 'Error' messages (which is to be expected), and doesn't leak any memory. Running valgrind (3.7.0) on Mac OS X 10.7.4 (using GCC 4.7.1), it is given a clean bill of health.
The problem is not, apparently, in this version of the code.
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <wchar.h>
char strlist[5][11] = {
{ "file01.txt" },
{ "file02.txt" },
{ "file03.txt" },
{ "file04.txt" },
{ "file05.txt" }
};
typedef struct DYNAMEM_DATA {
char *string;
int strlen;
} DYNAMEM_DATA;
typedef struct DYNAMEM_STRUCT {
struct DYNAMEM_DATA **data;
int num_elements;
} DYNAMEM_STRUCT;
enum { MB_OK = 0 };
static void destroy_dynamem_data(DYNAMEM_DATA *dd)
{
free(dd->string);
free(dd);
}
static void destroy_dynamem_struct(DYNAMEM_STRUCT *ds)
{
for (int i = 0; i < ds->num_elements; i++)
destroy_dynamem_data(ds->data[i]);
free(ds->data);
free(ds);
}
static void MessageBox(const void *null, const wchar_t *wcs, const char *ncs, int status)
{
if (null == 0 || status == MB_OK)
fprintf(stderr, "%s\n", ncs);
else
fwprintf(stderr, L"%s\n", wcs);
}
static const char *TEXT(const char *arg) { return arg; }
extern DYNAMEM_STRUCT *create_dynamem_struct(int num_elements, char *strlist);
DYNAMEM_STRUCT *create_dynamem_struct(int num_elements, char *strlist)
{
DYNAMEM_STRUCT *ds = (DYNAMEM_STRUCT *)calloc(1, sizeof(DYNAMEM_STRUCT));
wchar_t wstring[128];
//char len[3];
int i;
ds->data = (DYNAMEM_DATA **)calloc(num_elements, sizeof(DYNAMEM_DATA *));
ds->num_elements = num_elements;
for(i = 0; i < num_elements; i++) {
ds->data[i] = (DYNAMEM_DATA *)calloc(1, sizeof(DYNAMEM_DATA));
ds->data[i]->string = (char *)calloc(1, strlen(&strlist[i*11])+5);
ds->data[i]->strlen = strlen(&strlist[i*11]);
sprintf(ds->data[i]->string, "%s, %d", &strlist[i*11], ds->data[i]->strlen);
mbstowcs(wstring, ds->data[i]->string, 128);
MessageBox(NULL, wstring, TEXT("Error"), MB_OK);
}
return ds;
}
int main(void)
{
DYNAMEM_STRUCT *ds = create_dynamem_struct(5, strlist[0]);
destroy_dynamem_struct(ds);
return 0;
}

how to implement next() PHP function in C

I am tried to implement next() PHP function in C. if I have
The different to my implementation is I want to do this work with more one points. For example:
if I have two char * like:
char * a = "ac\0";
char * b = "bd\0";
and I call:
printf("%c", cgetnext(a));
printf("%c", cgetnext(b));
printf("%c", cgetnext(a));
printf("%c", cgetnext(b));
gets an output like: abcd
but I get abab
here is my code:
`#include <string.h>
#include <stdlib.h>
typedef struct
{
int pLocation;
int myindex;
int lastIndex;
} POINTERINFORMATION;
int __myIndex = 0;
int pointersLocationsLength = 0;
char * temparr = NULL;
POINTERINFORMATION pointersLocations[256];
int
plAdd (int p)
{
if (pointersLocationsLength >= sizeof(pointersLocations)) {
return -1;
} else {
pointersLocations[pointersLocationsLength].pLocation = p;
pointersLocations[pointersLocationsLength].lastIndex = 0;
pointersLocationsLength ++;
return pointersLocationsLength;
}
}
int
getPointer (int p, POINTERINFORMATION * out)
{
int i;
for (i = 0; i < pointersLocationsLength; i++)
{
if(pointersLocations[pointersLocationsLength].pLocation == p)
{
pointersLocations[i].myindex = i;
*out = pointersLocations[i];
return 1;
}
}
return 0;
}
void
getPointerIndex(char ** variable, int * val)
{
char * buf = malloc(256);
if(sprintf(buf,"%p", &variable) > 0){
*val = strtol(buf, NULL, 16 );
} else {
*val = -1;
}
}
int
inArrayOfPointers (int pointer)
{
POINTERINFORMATION pi;
return getPointer(pointer, &pi);
}
char
cgetnext(char * arr)
{
char * myarr;
const size_t size = sizeof(char *) + 1;
int pof;
myarr = malloc(size);
getPointerIndex (&arr, &pof);
if (inArrayOfPointers(pof)){
POINTERINFORMATION pi;
if (getPointer(pof, &pi))
{
myarr = (char *)*(int *)pi.pLocation;
__myIndex = pi.lastIndex;
++pointersLocations[pi.myindex].myindex;
} else {
return 0;
}
} else {
if (plAdd(pof) == -1) {
printf(" CANNOT ADD ELEMENT TO ARRAY\n");
exit(0);
} else {
myarr = arr;
__myIndex = 0;
}
}
if (strlen(myarr) == __myIndex) {
return 0;
} else {
temparr = malloc(size);
temparr = strdup(myarr);
return myarr[__myIndex];
}
}`
how to fix this? differents solutions for solve it are very apreciated! Thanks in advance.
If you are specifically interested in char* "arrays", then a simple solution might be to just increment the pointer. Note that if using dynamically allocated memory, you need to save the original pointer to free it. The same idea could be used for other data types as well.
This is an example of what I mean. cgetnext here just returns the character at the current position in the array and increments pointer (that is passed by address).
char cgetnext( char **p )
{
assert( p != NULL );
// check for end of string
if ( **p == '\0' )
return '\0';
return *(*p)++;
}
int main( int argc, char* argv[] )
{
char *a = "ac";
char *b = "bd";
printf( "%c", cgetnext(&a));
printf( "%c", cgetnext(&b));
printf( "%c", cgetnext(&a));
printf( "%c", cgetnext(&b));
}

Resources