Strange Behavior with String Arrays in C - c

I've been having some difficulties with strings in C - especially when it comes to File I/O. I've looked through some previous threads to see how to make string arrays in C, and I have come up with this.
void CreateBiomes()
{
const int STRING_LENGTH = 32;
const int BIOME_COUNT = 63;
const char *biomes[BIOME_COUNT][STRING_LENGTH+1] = {"beaches", "birch_forest", "birch_forest_hills", "cold_beach", "deep_ocean", "desert", "desert_hills", "extreme_hills", "extreme_hills_with_trees", "forest", "forest_hills", "frozen_ocean", "frozen_river", "hell", "ice_flats", "ice_mountains", "jungle", "jungle_edge", "jungle_hills", "mesa", "mesa_clear_rock", "mesa_rock", "mushroom_island", "mushroom_island_shore", "mutated_birch_forest", "mutated_birch_forest_hills", "mutated_desert", "mutated_extreme_hills", "mutated_extreme_hills_with_trees", "mutated_forest", "mutated_ice_flats", "mutated_jungle", "mutated_jungle_edge", "mutated_mesa", "mutated_mesa_clear_rock", "mutated_mesa_rock", "mutated_plains", "mutated_redwood_taiga", "mutated_redwood_taiga_hills", "mutated_roofed_forest", "mutated_savanna", "mutated_savanna_rock", "mutated_swampland", "mutated_taiga", "mutated_taiga_cold", "ocean", "plains", "redwood_taiga", "redwood_taiga_hills", "river", "roofed_forest", "savanna", "savanna_rock", "sky", "smaller_extreme_hills", "stone_beach", "swampland", "taiga", "taiga_cold", "taiga_cold_hills", "taiga_hills", "void"};
for(int i = 0; i <= BIOME_COUNT; i++)
{
printf("%s\n", *biomes[i]);
}
return;
}
The issue is - this code only works for "beaches" and "mutated_mesa" before the program crashes. Everything compiles great, it just won't process any of the other strings I've listed in my array, instead, it prints a (null). Why is this?

Try replacing the declaration
const char *biomes[BIOME_COUNT][STRING_LENGTH+1]
as follows.
const char biomes[BIOME_COUNT][STRING_LENGTH+1]

Your array was a 2-D array of pointers, and, you indexed one too many in the printf loop.
I have changed this to a 1-D array of pointers, and also removed the hard coded sizes. Instead I replaced the last string "void" with a NULL pointer, and used that to control the loop.
#include <stdio.h>
void CreateBiomes(void)
{
const char *biomes[] = {"beaches", "birch_forest", "birch_forest_hills", "cold_beach", "deep_ocean", "desert", "desert_hills", "extreme_hills", "extreme_hills_with_trees", "forest", "forest_hills", "frozen_ocean", "frozen_river", "hell", "ice_flats", "ice_mountains", "jungle", "jungle_edge", "jungle_hills", "mesa", "mesa_clear_rock", "mesa_rock", "mushroom_island", "mushroom_island_shore", "mutated_birch_forest", "mutated_birch_forest_hills", "mutated_desert", "mutated_extreme_hills", "mutated_extreme_hills_with_trees", "mutated_forest", "mutated_ice_flats", "mutated_jungle", "mutated_jungle_edge", "mutated_mesa", "mutated_mesa_clear_rock", "mutated_mesa_rock", "mutated_plains", "mutated_redwood_taiga", "mutated_redwood_taiga_hills", "mutated_roofed_forest", "mutated_savanna", "mutated_savanna_rock", "mutated_swampland", "mutated_taiga", "mutated_taiga_cold", "ocean", "plains", "redwood_taiga", "redwood_taiga_hills", "river", "roofed_forest", "savanna", "savanna_rock", "sky", "smaller_extreme_hills", "stone_beach", "swampland", "taiga", "taiga_cold", "taiga_cold_hills", "taiga_hills",
NULL };
for(int i = 0; biomes[i] != NULL; i++) { // changed loop control
printf("%s\n", biomes[i]); // changed argument passed
}
}
int main(void){
CreateBiomes();
return 0;
}
Please note that this function won't do much good, because biomes, a local variable, will not be accessible after the function returns.

Try this way, your code should work.
void CreateBiomes()
{
int BIOME_COUNT = 63;
char *biomes[]= {"beaches", "birch_forest", "birch_forest_hills", "cold_beach", "deep_ocean", "desert", "desert_hills", "extreme_hills", "extreme_hills_with_trees", "forest", "forest_hills", "frozen_ocean", "frozen_river", "hell", "ice_flats", "ice_mountains", "jungle", "jungle_edge", "jungle_hills", "mesa", "mesa_clear_rock", "mesa_rock", "mushroom_island", "mushroom_island_shore", "mutated_birch_forest", "mutated_birch_forest_hills", "mutated_desert", "mutated_extreme_hills", "mutated_extreme_hills_with_trees", "mutated_forest", "mutated_ice_flats", "mutated_jungle", "mutated_jungle_edge", "mutated_mesa", "mutated_mesa_clear_rock", "mutated_mesa_rock", "mutated_plains", "mutated_redwood_taiga", "mutated_redwood_taiga_hills", "mutated_roofed_forest", "mutated_savanna", "mutated_savanna_rock", "mutated_swampland", "mutated_taiga", "mutated_taiga_cold", "ocean", "plains", "redwood_taiga", "redwood_taiga_hills", "river", "roofed_forest", "savanna", "savanna_rock", "sky", "smaller_extreme_hills", "stone_beach", "swampland", "taiga", "taiga_cold", "taiga_cold_hills", "taiga_hills", "void"};
int i;
for(i = 0; i < BIOME_COUNT-1; i++)
{
printf("%s\n", biomes[i]);
}
return;
}

Related

how to remove certain words from a line of text in c

I got my code working to an extent, but I need some more help. If I needed to remove the word "an", from sentence: "I ate an apple whilst looking at an ape.", it only removes the first "an" and not the second, how do I repeat the loop so it deletes all "an"s? I need the final sentence, after the code has been ran, to be: "I ate apple whilst looking at ape.". That is the goal im trying to achieve
Sorry for not including the code.
Here it is:
#include "RemoveFromText.h"
#include <stdlib.h>
#include <string.h>
int findFirstSubstring(char textToChange[], char removeThis[])
{
int size = strlen(textToChange);
int subStringLength = strlen(removeThis);
for(int i=0; i<size; i++)
{
if(textToChange[i] == removeThis[0])
{
int j = 0;
while(textToChange[i+j] == removeThis[j])
{
j++;
if(j==subStringLength)
{
return i;
}
}
}
}
return -1;
}
void removeFromText( char textToChange[], char removeThis[])
{
int textLength = strlen(textToChange);
if(findFirstSubstring(textToChange, removeThis) >= 0)
{
int subStringIdx = findFirstSubstring(textToChange, removeThis);
int loopVariabele = 0;
for(loopVariabele = subStringIdx; loopVariabele<textLength; loopVariabele++)
{
textToChange[loopVariabele] = textToChange[loopVariabele + strlen(removeThis)];
}
}
}
Leveraging 'strstr', and 'memmove' standard "C" library functions
// Remove all occurences of 'source' from 'message'.
void removeAll(char *message, char *source)
{
int len = strlen(source) ;
for (char *x = message ; x=strstr(x, source) ; ) {
// Copy everything after 'source', including terminating nul.
memmove(x, x+len, strlen(x+len)+1) ;
} ;
}
Notes:
that solution that not properly address the trailing space(s) after a word. This can be addressed by chaning the 'memmove'.
Probably make sense to make the function return the number of substitutions, or some other meaningful result

Changing char[] in C

I looking for a answer and can't find nowhere. I hope you'll help me. I write a simple app which include struct with a name of worker and . But when i want to change value of name i can't do it. I don't know why. Maybe you can't help me or you know another ways to do it? My code:
struct workers {
char name[256]="no";
int pay=-1;
};
void addOne(struct workers work[20]) {
char name[256];
int i=0;
for (i = 0; work[i].name != "no"; i++) {}
printf_s("Enter name of worker: ");
scanf_s("%s", &name);
//-----error here-----
work[i].name = name;
}
int main()
{
int i;
struct workers work[20];
for (i = 0;i < 20; i++) {
if (work[i].name != "no") {
work[i].pay = 100 * i;
}
}
for (i = 0; i < 20; i++) {
printf_s("%s\t%d\n", work[i].name, work[i].pay);
}
return 0;
}
work[i].name = name;
The above line is where the problem is.
Change as below:
snprintf( work[i].name, sizeof(work[i].name), "%s", name);
What you have done is trying to change the base pointer of the array and not the name.
Also there were few more errors in the code, pls resolve them.
It is not possible to set default values to structure as you have done in C.
You have to write code to init each array instance name variable with "no" in a loop and then use one of the string comparison functions to compare the strings. And then call your addOne.

User entered string run a particular function in c

Guys so I'm working on the web service assignment and I have the server dishing out random stuff and reading the uri but now i want to have the server run a different function depending on what it reads in the uri. I understand that we can do this with function pointers but i'm not exactly sure how to read char* and assign it to a function pointer and have it invoke that function.
Example of what I'm trying to do: http://pastebin.com/FadCVH0h
I could use a switch statement i believe but wondering if there's a better way.
For such a thing, you will need a table that maps char * strings to function pointers. The program segfaults when you assign a function pointer to string because technically, a function pointer is not a string.
Note: the following program is for demonstration purpose only. No bounds checking is involved, and it contains hard-coded values and magic numbers
Now:
void print1()
{
printf("here");
}
void print2()
{
printf("Hello world");
}
struct Table {
char ptr[100];
void (*funcptr)(void)
}table[100] = {
{"here", print1},
{"hw", helloWorld}
};
int main(int argc, char *argv[])
{
int i = 0;
for(i = 0; i < 2; i++){
if(!strcmp(argv[1],table[i].ptr) { table[i].funcptr(); return 0;}
}
return 0;
}
I'm gonna give you a quite simple example, that I think, is useful to understand how good can be functions pointers in C. (If for example you would like to make a shell)
For example if you had a struct like this:
typedef struct s_function_pointer
{
char* cmp_string;
int (*function)(char* line);
} t_function_pointer;
Then, you could set up a t_function_pointer array which you'll browse:
int ls_function(char* line)
{
// do whatever you want with your ls function to parse line
return 0;
}
int echo_function(char* line)
{
// do whatever you want with your echo function to parse line
return 0;
}
void treat_input(t_function_pointer* functions, char* line)
{
int counter;
int builtin_size;
builtin_size = 0;
counter = 0;
while (functions[counter].cmp_string != NULL)
{
builtin_size = strlen(functions[counter].cmp_string);
if (strncmp(functions[counter].cmp_string, line, builtin_size) == 0)
{
if (functions[counter].function(line + builtin_size) < 0)
printf("An error has occured\n");
}
counter = counter + 1;
}
}
int main(void)
{
t_function_pointer functions[] = {{"ls", &ls_function},
{"echo", &echo_function},
{NULL, NULL}};
// Of course i'm not gonna do the input treatment part, but just guess it was here, and you'd call treat_input with each line you receive.
treat_input(functions, "ls -laR");
treat_input(functions, "echo helloworld");
return 0;
}
Hope this helps !

How do I display the searched string on the screen?

So, what I'm trying to do, is have the user search for a cheese and having it display it on the screen. I'm having trouble with the latter. I cant seem to display the string, but my code still runs. Here is my code:
#include<stdio.h>
#include<string.h>
char cheeses[][20] = {
"Cheddar",
"White Cheddar",
"Colby Jack",
"Gouda",
"Blue Cheese",
"Gorgonzola",
"Asiago",
"Limburger",
"Feta",
"Brie",
"Goat",
};
void find_cheese(const char *search_for)
{
int i;
for (i = 0; i < 5; i++) {
if (strstr(cheeses[i], search_for))
printf("Cheese %i: '%s'\n", i, cheeses[i]);
}
}
int main()
{
char search_for[20];
printf("Search for: ");
fgets(search_for, 20, stdin);
find_cheese(search_for);
return 0;
}
So what do I do in this case. I want it so that you can type in, "Lim," and have it display Limburger (in the future it will be able to display info on the cheese). How will I do this?
It looks okay, but you only search through the 5 first, and Limburger is too close to the end of the list.
This type of code is better to solve with a "sentinel", i.e. a special marker that is used to signify that the list has ended. For strings, you can represent the array as an array of pointers to strings rather than a fixed-size array, and then using NULL as the sentinel is pretty natural.
The array would become:
const char *cheeses[] = { "Cheddar", "White Cheddar", "Colby Jack",
/* ... rest of the cheeses ... */
NULL
};
then you can write the search loop like so:
int i;
for( i = 0; cheeses[i] != NULL; ++i )
{
/* Test and handling code here, against cheeses[i] just like before. */
}

Remove the duplicate from a String Using Pointers

#include<stdio.h>
char *removedps(char *x)
{
int Ar[256] = {0};
int ip=0;
int op=0;
char temp;
while(*(x+ip))
{
temp = (*(x+ip));
if (!Ar[temp]) {
Ar[temp] = 1;
*(x+ip) = *(x+op);
op++;
}
ip++;
*(x+op) = '\0';
}
return x;
}
int main()
{
char lo[] = "0001";
printf("%s",removedps(lo));
}
My code is not working
I have tried hard to see the error
All I GET IS the first character .
My idea is simple
make an array of 256 places
insert Zero into them
Then insert 1 for each character inside the string (on that position of the array)
your assignment looks to be the error here.
op is "out postiion", ip is "in position"
so it should be
*(x+op) = *(x+ip);
not the other way.
because *(x+op) = '\0';
is always run every iteration of the loop.
I'd probablly do it more like this ( using your method, which I probablly wouldn't use personally)
char *removedps(char *x)
{
int Ar[256] = {0};
char* start = x;
while(*x)
{
if (Ar[*x])
{ // remove the repeated character
memmove(x, x+1, strlen(x));
}
else
{
Ar[*x] = 1;
x++;
}
}
return start;
}
also, I'd name it remove_duplicate_chars or something, not a fan of cryptic abbreviations.
At the end of the loop, you do *(x+op)='\0';, and then, in the next iteration, you do *(x+ip)=*(x+op);, so from the 2sd iteration, you put there 0.
try do something like:
for (op=ip=0;x[ip];ip++) {
if (!Ar[x[ip]]++) x[op++]=x[ip];
}
x[op]=0;

Resources