C working with strings and SEGFAULT - c

Hello and sorry for my bad english.
I am starting with C language, but I didnt get pointers well...
I searched for similar topics, but I didnt get it from them, so I created own topic.
I have got main function, where I call function newSpeak.
There is my code of newSpeak, but there isnt everything...
char * newSpeak ( const char * text, const char * (*replace)[2] )
{
int i;
char * alpha;
for(i=0;i<4;i++)
{
alpha=strstr(text, replace[0][4]);
if(alpha[0])
strncpy (alpha,replace[1][0],10);
}
return 0;
}
Thanks for answering
EDIT: I have found source of the problem.
It works, when I dont use for cycle and run it once. But it doesnt work even when the condition in for cycle is i<1, which should make it run only once...This is strange for me...

alpha=strstr(text, replace[0][4]);
if(alpha[0])
// looks crashy
man strstr:
These functions return a pointer to the beginning of the substring,
or NULL if the substring is not found.
EDIT:
It is difficult to tell what you are trying to do, but below find an arbitrary adaptation of your code. If it were my program, I would write it very differently. I mention that because I do not want someone to read this and think it is the way it should be done.
#include <stdio.h>
#include <string.h>
void newSpeak (char *text, const char *replace[4][2])
{
int i, j;
char *alpha;
for (i = 0; i < 4; i++) {
if (alpha = strstr(text, replace[i][0])) {
for (j = 0; alpha[j] && replace[i][1][j]; j++)
alpha[j] = replace[i][1][j];
}
}
}
int main ()
{
char buf[100] = "abc";
const char *replace[4][2] = {
{ "a", "e" },
{ "b", "f" },
{ "c", "g" },
{ "d", "h" },
};
newSpeak(buf, replace);
puts(buf);
}

The line
strncpy (alpha,replace[1][0],10);
should have generated a compiler warning (and NEVER ignore compiler warnings). The function prototype is
char *strncpy( char *dest, char *source, int n);
But you are passing it replace[1][0] which is a character. It might work if you passed
strncpy( alpha, &replace[1][0], 10);
Even then I still worry. It could be that since alpha is pointing to a block of memory in the block pointed to by text which is a const char*, that you are not allowed to modify that memory.
EDIT I think my first point is wrong - I misread your prototype. But I'm pretty sure the second point is valid (and probably the reason for the segfault).
second edit
It is possible that text does not have sufficient memory allocated to have 10 characters copied into it from replace. Realize that the thing you are matching against (replace[0][4]) and the thing you are copying (replace[1][0]]) are not the same thing; also, you are looping over i but not using that value ... makes me wonder if there is a typo (I am not clairvoyant and cannot figure out what you wanted to change from loop to loop).
You need to check the size of the thing you are copying into:
strncpy(alpha, replace[1][0], (strlen(alpha)<10)?strlen(alpha):10);
would ensure you are copying no more than 10 characters, and no more than there's space in alpha.
This is "on top of" everything else already pointed out (of which using if (alpha!=NULL) instead of if(alpha[0]) is a big one.)
EDIT 3 - I think I figured out the majority of the problems with your code now... see http://codepad.org/YK5VyGAn for a small "working" sample.
Issues with your code included:
You declare text as const char*, then proceed to modify it
You declare replace as const char* (*replace)[2], then address element replace[0][4] (4 > 2...)
You assign the return value of strstr to alpha; this could be NULL (no match), yet you test for alpha[0] (which will fail if alpha == NULL).
When you copied the replacement string, you copied "up to 10 characters" - regardless of whether (a) the target string could accommodate this, and (b) the source string had this many characters. The result might be that you copy the full source string (including the terminating '\0') so that you will not find another match afterwards (you have "deleted" the rest of the string). And then you will run into the "strstr returns NULL" error...
Not sure (without seeing your input string or "replace" strings) which of these actually caused your code to fail - I have written a small program that addresses all of these mistakes. You can find it at http://codepad.org/4jSOnmPy - reproduced here:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MIN(a,b) (a>b)?(b):(a)
char * newSpeak (const char *text, const char *(*replace)[5] ){
int ii=0, n;
char *alpha, *beta;
printf("length of input string is %d\n", strlen(text));
beta = malloc(strlen(text)+1);
printf("allocated %d bytes\n", strlen(text)+1);
fflush(stdout);
strcpy(beta, text);
printf("copy OK: beta now %s\n", beta);
fflush(stdout);
for(ii = 0; ii < 4; ii++) {
// alpha=strstr(beta, replace[0][0]);
alpha=strstr(beta, "a");
printf("alpha is '%s'\n", alpha);
fflush(stdout);
if(alpha!=NULL) {
char *rs;
rs = replace[1][ii];
printf("ii = %d; alpha now: '%s'\n", ii, alpha);
fflush(stdout);
n = MIN(strlen(alpha), strlen(rs));
printf("n is now %d\n", n);
fflush(stdout);
printf("going to copy at most %d characters from '%s' into '%s'\n", n, rs, alpha);
fflush(stdout);
strncpy (alpha,rs,n);
printf("beta is now '%s'\n", beta);
fflush(stdin);
}
else printf("no match found\n");
}
return beta;
}
int main(void) {
char* r[2][5]={{"a","b","c","d", "e"}, {"o","e","i","u","s"}};
char* myText = "this is a vary sally strang";
printf("NewSpeak: %s\n", "hello world");
printf("converted: %s\n", newSpeak(myText, r));
return 0;
}
Output:
NewSpeak: hello world
length of input string is 27
allocated 28 bytes
copy OK: beta now this is a vary sally strang
alpha is 'a vary sally strang'
ii = 0; alpha now: 'a vary sally strang'
n is now 1
going to copy at most 1 characters from 'o' into 'a vary sally strang'
beta is now 'this is o vary sally strang'
alpha is 'ary sally strang'
ii = 1; alpha now: 'ary sally strang'
n is now 1
going to copy at most 1 characters from 'e' into 'ary sally strang'
beta is now 'this is o very sally strang'
alpha is 'ally strang'
ii = 2; alpha now: 'ally strang'
n is now 1
going to copy at most 1 characters from 'i' into 'ally strang'
beta is now 'this is o very silly strang'
alpha is 'ang'
ii = 3; alpha now: 'ang'
n is now 1
going to copy at most 1 characters from 'u' into 'ang'
beta is now 'this is o very silly strung'
converted: this is o very silly strung
Note - I added lots of "useless" output, including fflush(stdout); statements. This is a good way to ensure that debug printout shows you exactly how far into a program you got, and what was going on before it crashed - without the fflush it's possible you are missing many lines of output (because they never "made it to the screen").
It's obvious from the above that if your replacement strings are a different length than the string they replace, you will get some strange overwriting (I left both search and replace string length at 1 but there is no reason why that should be so).
I hope this helps!

Related

Trying to return the char in the middle of an input (char array) gives "segmentation fault (core dumped)"? [duplicate]

This question already has answers here:
Why does C's printf format string have both %c and %s?
(11 answers)
Closed 4 years ago.
In a nutshell, I have to be able to return the character in the middle of an input (char array) for part of our first C assignment. What I have so far, however, is code that returns "Segmentation fault (core dumped)". I read into this a little bit, and learned that essentially I may be trying to access/modify data that is "not available to me", so-to-speak. Here is my code:
#include <stdio.h>
#include <string.h>
char input[30];
int inputLen;
char midChar;
int main()
{
printf("Type in some text, and the press the Return/Enter key: ");
fgets(input,sizeof(input),stdin);
printf("\nYour input: %s",input);
inputLen = strlen(input)-1;
printf("Length of your input is %d characters.",inputLen);
if((inputLen % 2) == 0) {
midChar = input[(inputLen/2)+1]; // >>> PROBLEM HERE <<<
}
else {
midChar = input[((inputLen+1)/2)+1]; // >>> PROBLEM HERE <<<
}
printf("%s",midChar);
return 0;
}
The two lines with >>> PROBLEM HERE <<< are the lines which I believe I've narrowed down to be the source of the problem.
Please Note: I have taken an introductory class in Java, and last semester took a class half-devoted to MATLAB, so I do have a little bit of programming intuition -- However, I am a 100% beginner in C, so I would appreciate some clear elaboration behind any help you guys may offer. I am not familiar with most functions/syntax unique to C, so I'm sure there will be cringe-worthy lines of code above for those well-versed in this language. If this is the case, feel free to include any other tips in your answers. Thanks!
You're printing a char with %s, so the program is treating your input as a pointer (to a char array). It's not a valid such thing.
You meant %c for a single character.
Your compiler should tell you about this. Turn warnings on!
A late addition:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
// This will be the default value if a string of length 0 is entered
char midChar = 0;
int inputLen;
int bufferLen = 31;
char* input = (char*)malloc(sizeof(char) * bufferLen);
printf("Type in some text, and the press the Return/Enter key: ");
fgets(input, bufferLen, stdin);
printf("\nYour input: %s", input);
inputLen = strlen(input);
if (input[inputLen - 1] == '\n') {
inputLen--; // ignore new line character
}
printf("Length of your input is %d characters.\n", inputLen);
if (inputLen > 0) {
midChar = input[inputLen / 2]; // take right of middle for even number
}
printf("%c\n", midChar);
return 0;
}
In your previous post you used sizeof(input) which is not recommended for reasons described in this post. It is better practice to hold the length of the array in a separate variable, here bufferLen.
Also the use of global variables here input inputLen midChar is generally discouraged as they lead to unexpected behaviour during linking and make program flow harder to understand.
I initialised the memory for the buffer dynamically so the bufferLen could be changed in the program.
When computing the length of the input one must consider the newline character \n which is retained if a small enough string is entered but not if the entered string exceeds the bufferLen.
For strings with even lengths I arbitrarily took the character to the right. The inputLen zero case is also handled.
This whole answer is only an addition to the first one which already found the bug correctly, because I was late to the party.
Other than print char problem, I think there is also a problem at where you indicated.
ex. if input string is abc, inputLen will be 3, midchar index should be at 1 since array index in C start from 0. However ((inputLen+1)/2)+1 gives 3. This probably won't directly cause the segfault but will give wrong answer.
You can replace
if((inputLen % 2) == 0) {
midChar = input[(inputLen/2)+1]; // >>> PROBLEM HERE <<<
}
else {
midChar = input[((inputLen+1)/2)+1]; // >>> PROBLEM HERE <<<
}
with
midChar = input[inputLen/2];
since C will truncate when doing integer division.
a b c -> 3/2 = 1
[0] [1] [2]
a b c d -> 4/2 = 2
[0] [1] [2] [3]
Other than that, you also need to make sure the inputLen is not 0
Although "pretty lady" (#LightnessRasesInOrbit) up here is correct, let me explain what is happening when you do this:
printf("%s\n", charVar);
or this:
printf("%s\n", intVar);
or this:
printf("%s\n", floatVar);
Or when you print things using pritnf() with %s. You have to understand how does printf ("%s", string) work!! So when printf gets %s it looks for C string or in other words, character array terminated with '\0'. If it does not '\0' it will segfault. In depth, printf() works like this:
char name[4];
printf("Hello ", name);
now printf does following:
gets the size of 1st variable ("Hello")
gets the size of 2nd variable (name) How? Simple by this loop:
int varSize;
for (varSize = 0; varSize != '\0'; ++varSize);
moves "Hello" into buffer
Determine the size of second parameter. How, by doing this:
does following
if ("%d")
// read intVar and attach it to the buffer
if ("%f")
// read floatVar and attach it to the buffer
if ("%s")
for (int i = 0; stringVar[i] != '\0'; ++i)
// push each char into the buffer
So I hope you see what is happening if one of for() loops does not find '\0' character. If you do good if you don't well it continues reading through until it segfaults.
NOTE:
This is oversimplified pseudo code on how printf() works and is not actual implementation, this is only for OP to understand what is going on.

Difficulty printing char pointer array

I've been struggling on this problem all day now, and looking at similar examples hasn't gotten me too far, so I'm hoping you can help! I'm working on the programming assignment 1 at the end of CH 3 of Operating Systems Concepts if anyone wanted to know the context.
So the problem is to essentially create a command prompt in c that allows users to input a command, fork and execute it, and save the command in history. The user can enter the command 'history' to see the 10 most recent commands printed out. The book instructed me to store the current command as a char pointer array of arguments, and I would execute the current one using execvp(args[0], args). My professor added other requirements to this, so having each argument individually accessible like this will be useful for those parts as well.
I decided to store the history of commands in a similar fashion using an array of char pointers. So for example if the first command was ls -la and the second command entered was cd.. we would have history[0] = "ls -la" and history[1] = "cd..". I'm really struggling getting this to work, and I'm fairly certain I'm screwing up pointers somewhere, but I just can't figure it out.
In main I can print the first word in the first command (so just ls for ls -la) using arg_history[0] but really can't figure out printing the whole thing. But I know the data's there and I verify it when I add it in (via add_history function) and it's correct! Even worse when I pass it to the get_history function made for printing the history, it prints a bunch of gibberish. I would greatly appreciate any help in understanding why it's doing this! Right now I have a hunch it's something to do with passing pointers incorrectly between functions, but based on what I've been looking at I can't spot the problem!
/**
* Simple shell interface program.
*
* Operating System Concepts - Ninth Edition
* Copyright John Wiley & Sons - 2013
*/
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#define MAX_LINE 80 /* 80 chars per line, per command */
#define HIST_LENGTH 10
void get_input(char *args[], int *num_args, char *history[], int *hist_index);
void get_history(char *history[], int hist_index);
void add_history(char *history[], char *added_command, int *hist_index);
int main(void)
{
char *args[MAX_LINE/2 + 1]; /* command line (of 80) has max of 40 arguments */
char *arg_history[HIST_LENGTH];
int num_args;
int hist_index;
int should_run = 1;
int i;
while (should_run){
printf("osh>");
fflush(stdout);
get_input(args, &num_args, arg_history, &hist_index);
//printf("%s\n", arg_history[0]); //incorrectly prints up to the first space
//printf("%s\n", args[0]) //prints the correct arg from the last command (eg. for 'ls -la' it prints ls for args[0] and -la for args[1])
if (strcmp(args[0], "history") == 0) {
get_history(arg_history, hist_index);
}
}
return 0;
}
void get_input(char *args[], int *num_args, char *history[], int *hist_index) {
char input[MAX_LINE];
char *arg;
fgets(input, MAX_LINE, stdin);
input[strlen(input) - 1] = NULL; // To remove new line character - the compiler doesn't like how I'm doing this
add_history(history, input, hist_index);
arg = strtok(input, " ");
*num_args = 0;
while(arg != NULL) {
args[*num_args] = arg;
*num_args = *num_args + 1;
arg = strtok(NULL, " ");
}
}
void get_history(char *history[], int hist_index) {
int i;
for (i = 0; i < HIST_LENGTH; i++) {
printf("%d %s\n", hist_index, *history);
// prints gibberish
hist_index = hist_index - 1;
if (hist_index < 1) {
break;
}
}
}
void add_history(char *history[], char *added_command, int *hist_index) {
int i;
for (i = HIST_LENGTH-1; i > 0; i--) {
history[i] = history[i-1];
}
history[0] = added_command;
*hist_index = *hist_index + 1;
//printf("%s\n", history[0]); prints correctly
}
Update:
I made the changes suggested by some of the solutions including moving the pointer to input out of the function (I put it in main) and using strcpy for the add_history function. The reason I was having an issue using this earlier was because I'm rotating the items 'up' through the array, but I was accessing uninitialized locations before history was full with all 10 elements. While I was now able to print the arg_history[0] from main, I was still having problems printing anything else (eg. arg_history[1]). But more importantly, I couldn't print from the get_historyfunction which is what I actually needed to solve. After closer inspection I realized hist_index is never given a value before it's used to access the array. Thanks for the help everyone.
input[strlen(input) - 1] = NULL; // To remove new line character - the compiler doesn't like how I'm doing this
Of course it doesn't. There are many things wrong with this. Imagine if strlen(input) is 0, for example, then strlen(input) - 1 is -1, and you're accessing the -1th item of the array... not to mention NULL is a pointer, not a character value. You probably meant input[strlen(input) - 1] = '\0';, but a safer solution would be:
input[strcspn(input, "\n")] = '\0';
history[0] = added_command;
*hist_index = *hist_index + 1;
//printf("%s\n", history[0]); prints correctly
This prints correctly because the pointer value added_command, which you assign to history[0] and which points into input in get_command is still alive. Once get_command returns, the object that pointer points to no longer exists, and so the history[0] pointer also doesn't exist.
You should know you need to use strcpy to assign strings by now, if you're reading a book (such as K&R2E). Before you do that, you need to create a new object of suitable size (e.g. using malloc)...
This is a common problem for people who aren't reading a book... Which book are you reading?
printf("%d %s\n", hist_index, *history);
// prints gibberish
Well, yes, it prints gibberish because the object that *history once pointed to, before get_command returned, was destroyed when get_command returned. A book would teach you this.
See also Returning an array using C for a similar explanation...
Here are some description of strtok(). Because you just put the pointer of input to your history list instead of putting a copy, you'd only print out the first word.
char *strtok(char *str, const char *delim)
Parameters
str -- The contents of this string are modified and broken into smaller strings (tokens).
delim -- This is the C string containing the delimiters. These may vary from one call to another.

C - Replace substring in string

As a part in my process to learn C I am developing a couple of functions for string manipulations. One of these has the function of replacing substrings within a string, and is raising some questions. I am working in C99; compiling on Mac OS Sierra and FreeBSD.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *repstr(char input[], char rep[], char new[]) {
char *output = malloc(strlen(input)*5); // <- Question 2
int replen = strlen(rep);
int newlen = strlen(new);
int a, b, c = 0;
// printf("input: %ld\t%s\n", strlen(input), input); // <- Question 1
while(input[a]) {
if(input[(a+b)] == rep[b]) {
if(b == replen - 1) {
strcat(output, new);
a += replen;
c += newlen;
b=0;
}
else b++;
} else {
output[c] = input[a];
a++;
c++;
}
}
return output;
}
int main() {
char buffer[] = "This is the test string test string test test string!";
char rep[] = "test";
char new[] = "tested";
int len = strlen(buffer);
char output[len+5];
printf("input: %d\t%s\n", len, buffer); // <- Question 1
strcpy(output, repstr(buffer, rep, new));
printf("output: %ld\t%s\n", strlen(output), output);
return 0;
}
Question 1: When this line is executed in main() it causes a segfault. However, when executed within the function everything seems to work fine. Why?
Question 2: I have realized that I need a pretty large piece of memory allocated for the output to look as expected. strlen(input)*5 is an arbitrary number which seems to work, but why do I get seemingly 'random' errors when lowering the number?
NB! As this is a part of my process to learn coding in C I am not primarily interested in (more efficient) pre-fab solutions for solving the problem (already have them), but to explain the two questions listed - so that I can solve the problem myself.
Also; this is my first post in the SO forums. Hello.
Question 1: When this line is executed in main() it causes a segfault.
However, when executed within the function everything seems to work
fine. Why?
No, printf("input: %d\t%s\n", len, buffer); // <- Question 1 is not the cause of your segfault.
printf("output: %ld\t%s\n", strlen(output), output);
This part is, strlen doesn't return int but it returns size_t. As noted in the comments, use %zu to print it out.
Also, while(input[a]) will stop at the NULL terminator which means that your output will never hold a terminator and thus printf will keep on reading, you should add it at the end:
output[c] = '\0';
Also, as noted by #LPs in the comments, you should zero initialize the variables you work with :
int a = 0, b = 0, c = 0;
Question 2: I have realized that I need a pretty large piece of memory
allocated for the output to look as expected. strlen(input)*5 is an
arbitrary number which seems to work, but why do I get seemingly
'random' errors when lowering the number?
Probably because you haven't allocated enough memory. Because the string length depends on runtime factors there's no way to know the exact memory needed you should allocate the maximum amount required:
char *output = malloc(strlen(input) * strlen(new) + 1);

printf() isn't being executed

I wanted to write a program which counts the occurrences of each letter in a string, then prints one of each letter followed by the count for that letter.
For example:
aabbcccd -
Has 2 a, 2 b, 3 c, and 1 d
So I'd like to convert and print this as:
a2b2c3d1
I wrote code (see below) to perform this count/conversion but for some reason I'm not seeing any output.
#include<stdio.h>
main()
{
char array[]="aabbcccd";
char type,*count,*cp=array;
while(cp!='\0'){
type=*cp;
cp++;
count=cp;
int c;
for(c=1;*cp==type;c++,cp++);
*count='0'+c;
}
count++;
*count='\0';
printf("%s",array);
}
Can anyone help me understand why I'm not seeing any output from printf()?
char array[]="aabbcccd";
char type,*count,*cp=array;
while(cp!='\0'){
*cp is a pointer it's pointing to the address of the start of the array, it will never be == to a char '\0' so it can't leave the loop.
You need to deference the pointer to get what it's pointing at:
while(*cp != '\0') {
...
Also, you have a ; after your for loop, skipping the contents of it:
for(c=1;*cp==type;c++,cp++); <-- this ; makes it not execute the code beneath it
After fixing both of those problems the code produces an output:
mike#linux-4puc:~> ./a.out
a1b1c2cd
Not the one you wanted yet, but that fixes your problems with "printf not functional"
Incidentally, this code has a few other major problems:
You try to write past the end of the string if the last character appears once (you write a '1' where the trailing '\0' was, and a '\0' one character beyond that.
Your code doesn't work if a character appears more than 9 times ('0' + 10 is ':').
Your code doesn't work if a character appears more than 2 times ("dddd" doesn't become "d4"; it becomes "d4dd").
Probably line-buffering. Add a \n to your printf() formatting string. Also your code is very scary, what happens if there are more than 9 of the same character in a row?
1) error correction
while(*cp!='\0'){
and not
while(cp!='\0'){
2) advice
do not use array[] to put in your result user another array to put in your rusel it's more proper and eay
I tried to solve your question quickly and this is my code:
#include <stdio.h>
#define SIZE 255
int main()
{
char input[SIZE] = "aabbcccd";/*input string*/
char output[SIZE]={'\0'};/*where output string is stored*/
char seen[SIZE]={'\0'};/*store all chars already counted*/
char *ip = input;/*input pointer=ip*/
char *op = output;/*output pointer = op*/
char *sp = seen;/*seen pointer=sp*/
char c,count;
int i,j,done;
i=0;
while(i<SIZE && input[i]!='\0')
{
c=input[i];
//don't count if already searched:
done=0;
j=0;
while(j<SIZE)
{
if(c==seen[j])
{
done=1;
break;
}
j++;
}
if(done==0)
{//if i never searched char 'c':
*sp=c;
sp++;
*sp='\0';
//count how many "c" there are into input array:
count = '0';
j=0;
while(j<SIZE)
{
if(ip[j]==c)
{
count++;
}
j++;
}
*op=c;
op++;
*op=count;
op++;
}
i++;
}
*op='\0';
printf("input: %s\n",input);
printf("output: %s\n",output);
return 0;
}
It's not a good code for several reasons(I don't check arrays size writing new elements, I could stop searches at first empty item, and so on...) but you could think about it as a "start point" and improve it. You could take a look at standard library to copy substring elements and so on(i.e. strncpy).

strcpy and printf a multidimensional char array C

Say I have an array
char messages[10][2][50];
What is the correct syntax for strcpy, in order to get the data into one of the strings (inner most char array of size 50) and then the corresponding convention to supply it to printf via %s?
For that matter, am I declaring the array subscripts in the correct order? It is intended to be 10 lots of, pairs (of 2) strings. Each string being 50 chars wide.
01{{50 chars},{50 chars}}
02{{50 chars},{50 chars}}
...
09{{50 chars},{50 chars}}
10{{50 chars},{50 chars}}
Various internet sources seem to conflict on which subscript to omit and, whatever I try seems to produce unintended results.
e.g. Could you fill in the blanks to the following
strcpy(message???, "Message 1 Part 1");
strcpy(message???, "m1 p2");
strcpy(message???, "m2 p1");
strcpy(message???, "m2 p2");
strcpy(message???, "m3 p1");
strcpy(message???, "m3 p1");
//So on...
int i;
for(i=0;i<10;i++)
printf("%s, %s\n", message???, message???);
Such that the array has a structure of and holds:
01{{"Message 1 Part 1\0"},{"m1 p2\0"}}
02{{"m2 p1\0"},{"m2 p2\0"}}
01{{"m3 p1\0"},{"m3 p2\0"}}
//So on...
And outputs as such
Message 1 part 1, m2 p2
m2, p2
m3, p3
and so on
I just wrote a quick program to show the things you've asked about... loading them up at declaration, strncpy into one of them, and then printing them out.
Hope it helps
edit: I kind of hate magic numbers so I almost totally removed them
edit: I've added alternatives Tommi Kyntola and I were talking about in the comments
#include <stdio.h>
#include <string.h>
// safe string copy macro, terminates string at end if necessary
// note: could probably just set the last char to \0 in all cases
// safely if intending to just cut off the end of the string like this
#define sstrcpy(buf, src, size) strncpy(buf, src, size); if(strlen(src) >= size) buf[size-1] = '\0';
#define MSGLIMIT 10
#define MSGLENGTH 30
#define MSGFIELDS 2
#define MSGNAME 0
#define MSGTEXT 1
int main(void) {
char messages[MSGLIMIT][MSGFIELDS][MSGLENGTH] = { {"bla", "raa"},
{"foo", "bar"}
};
int i;
char *name1 = "name16789012345678901234567890";
char *text1 = "text16789012345678901234567890";
char *name2 = "name26789012345678901234567890";
char *text2 = "text26789012345678901234567890";
char *name3 = "name36789012345678901234567890";
char *text3 = "text36789012345678901234567890";
// doesn't set last char to \0 because str overruns buffer
// undocumented result of running this, but likely to just get the name2 string
// as that'll be the very next thing in memory on most systems
strncpy(messages[2][MSGNAME], name1, MSGLENGTH); // 2 because it's the next empty one
strncpy(messages[2][MSGTEXT], text1, MSGLENGTH);
// alternative suggested by Tommi Kyntola
// printf family are more complicated and so cost more cpu time than strncpy
// but it's quick and easy anywhere you have string.h and fine most of the time
snprintf(messages[3][MSGNAME], MSGLENGTH, "%s", name2);
snprintf(messages[3][MSGTEXT], MSGLENGTH, "%s", text2);
// uses the define macro at the top of the page to set the last char to \0 if
// otherwise not set by strncpy, adds a little weight but still the better option
// if performance of this section of code is important
sstrcpy(messages[4][MSGNAME], name3, MSGLENGTH);
sstrcpy(messages[4][MSGTEXT], text3, MSGLENGTH);
for(i = 0; i < 5; i++) // 5 because that's how many I've populated
printf("%s : %s\n", messages[i][MSGNAME], messages[i][MSGTEXT]);
return 0;
}
You can ommit greatest subscription(in you ex. it is 10), as it can be calculated by compiler according to remained subscriptions.
To pass layers of 50 elements use pointers: (*messages)[10][2] - will be pointer on layer of 50 elements
I would use:
assuming you want to copy to char* new_buff
memcpy(new_buff, messages, 10*2*50);
you can do a 3 nested loop and use strncpy.
don't use strcpy... it is unsecured
As has been pointed out, best to use strncpy, or as in my example below, use asserts, to prevent possible buffer overruns. There's a tiny increase in performance in strcpy vs strncpy.
#define FIRST_OF_PAIR 0
#define SECOND_OF_PAIR 1
int message_num = 7;
char messages[10][2][50];
char *string = "hello";
assert(strlen(string) < 50);
assert(message_num > 0 && message_num < 10);
strcpy(messages[message_num][SECOND_OF_PAIR], "Hello");
printf("%s", messages[message_num][SECOND_OF_PAIR]);
It will be
strcpy(message[0][0], "Message 1 Part 1");
strcpy(message[0][1], "m1 p2");
strcpy(message[2][0], "m2 p1");
strcpy(message[2][1], "m2 p2");
strcpy(message[3][0], "m3 p1");
strcpy(message[3][1], "m3 p2");
for(i=0;i<10;i++)
printf("%s, %s\n", message[i][0], message[i][1]);
try to get the concept.

Resources