Storing characters in array using pointers - c

I am supposed to create an array with the fixed size (let’s say 5x5). I am supposed to fill it with words typed as command line parameters. I can use only pointers. Obviously I have to create two dimensional array[5][5]. I can’t use more than 25 letters ( I will make if statements ). I am going replace white space with some symbol ($ or something). The problem is I don’t know how to connect those command line parameters with array using only pointers.

You need to use the argc and argv arguments from the main function.
Here is an example.
#include <stdio.h>
int main(int argc, char *argv[])
{
for (unsigned i = 1; i < argc; i++)
{
printf("Word %u is: %s\n", i, argv[i]);
}
return 0;
}
You compile it using gcc main.c -o a.exe.
And run it using a.exe hello world.
Edit:
Further to your comment.
You can create an array of pointers like so:
#include <stdio.h>
#include <string.h>
#include <stddef.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
char *my_array_of_strings[5]; // up to 5 strings
// populate your array
for (unsigned i = 1; i < argc; i++)
{
my_array_of_strings[i - 1] = malloc(strlen(argv[i]) + 1);
if (NULL == my_array_of_strings[i - 1])
{
printf("oh no, memory failure");
break;
}
memcpy(my_array_of_strings[i - 1], argv[i], strlen(argv[i]) + 1);
printf("word is %s\n", my_array_of_strings[i - 1]);
}
return 0;
}

Related

why malloc yields error after long argv arguments?

I have written a program where it reads some filenames and a word from command line arguments. The first argument will be a word and remaining will be filenames. It fills a structure that I have defined.
However for small arguments, the program works correctly but for large ones malloc gives corrupted top size error.
Below is just initial code of the program:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define FILENAME_LIM 256
#define WORD_LIM 256
struct data {
char filename[FILENAME_LIM];
char word[WORD_LIM];
};
int main(int argc, char *argv[]) {
if (argc < 3) {
printf("usage: ./a.out word filename1 filename2 filename3 filename4 filename5 ...\n");
exit(EXIT_FAILURE);
}
char word[WORD_LIM];
strcpy(word, argv[1]);
int files = argc - 2;
struct data *dataarray = (struct data *)malloc(sizeof(sizeof(struct data) * files));
if (!(dataarray)) {
perror("malloc");
exit(EXIT_FAILURE);
}
for (int i = 0; i < files; i++) {
strcpy(dataarray[i].filename, argv[i + 2]);
for (int ii = 0; ii < strlen(dataarray[i].filename) + 1; ii++) {
printf("filename[%d] = %c (%d), argv[%d] = %d\n",
i, dataarray[i].filename[ii], dataarray[i].filename[ii],
i, argv[i + 2][ii]);
}
}
return 0;
}
I tried everything, but when I give some large filename in argv such as "../../../C Programs/chess.c", malloc yields an error. I want to know what is making corrupted top size.
sizeof(struct data) * files
is a valid size. Any multiple of a size is a size.
sizeof(sizeof(struct data) * files)
is like saying sizeof(23422). I don't know what that means, and odds are the runtime isn't behaving properly either.
Restrict your use of sizeof(...) to processing type arguments.

How to pass whole array of words given in command line arguments direct to function?

I want to ask is there a diffrent to pass words from comand line array of strings to this function other than this:
//input given: $> ./main tail degree sheet nose noise base boy
//declaration of function: int ll_insert_words(struct linked_list_t* ll, int N, ...);
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include "linked_list.h"
int main(int argc,char** argv) {
if (argc <= 1) {
printf("Not enough arguments");
return 9;
}
struct linked_list_t* ll = ll_create();
if (ll == NULL) {
printf("Failed to allocate memory");
return 8;
}
for (int i = 0; i < argc - 1; i++) {
ll_insert_words(ll, 1, *(argv + 1 + i));
}
ll_display(ll);
ll_clear(ll);
free(ll);
return 0;
}
I want to know how can I pass the array directly to function. By that I mean:
ll_insert_words(ll, 12, "list", "among", "sharp", "has", "coat", "consonant", "old", "trouble", "require", "wear", "band", "real");
But to swap all "list" etc. to the array.
You'll need to pass a (char**) pointer to the function. Change the function declaration to:
int ll_insert_words(struct linked_list_t* ll, char** words, int number_of_words);
And then call it with these parameters:
ll_insert_words(ll, argv, argc);
Then in the function write something along these lines:
for (i = 0; i < number_of_words; i++)
{
ll_insert(ll, words[i]);
}

How to print a variable length string of a single character

I have a need to print a variable number of a given character in conjunction with my formatted output. I was looking for something similar or equivalent to the VBA function String(num, char), but haven't been able to find any. I've written a function to do the job but if there is something built-in that does it I'd love to know. Here's what I have. For the purpose of testing I'm using a sloppy implementation of argv[].
What I want to is print out something like this;
Here's the rough implementation I've come up with;
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
const char * make_string(int num, char character)
{
char *strchars = malloc(num);
for (int i = 0; i < num; i++)
strchars[i] = character;
return strchars;
}
int main(int argc, char *argv[])
{
for (int i = 1; i < argc; i++) {
printf("%s\n", make_string(strlen(argv[i]),'_'));
printf("%s%c %s\n", make_string(strlen(argv[i]),'_'),'|', argv[i]);
}
}
Is there a library function for printing strings of repeating characters like this?
Credit for this answer goes to UmamaheshP for pointing me in the right direction with a comment. This is what I was looking for and was adapted from an example he linked to.
#include <stdio.h>
#include <string.h>
int main (int argc, char *argv[]) {
int i;
char *pad = "________________";
for (i = 1; i < argc; i++)
printf ("%.*s\n%.*s%c %s\n", strlen(argv[i]),
pad,strlen(argv[i]), pad, '|', argv[i]);
}

Accept non ASCII characters

Consider this program:
#include <stdio.h>
int main(int argc, char* argv[]) {
printf("%s\n", argv[1]);
return 0;
}
I compile it like this:
x86_64-w64-mingw32-gcc -o alpha alpha.c
The problem is if I give it a non ASCII argument:
$ ./alpha róisín
r�is�n
How can I write and/or compile this program such that it accepts non ASCII
characters? To respond to alk: no, the program is printing wrongly. See
this example:
$ echo Ω | od -t x1c
0000000 ce a9 0a
316 251 \n
0000003
$ ./alpha Ω | od -t x1c
0000000 4f 0d 0a
O \r \n
0000003
The easiest way to do this is with wmain:
#include <fcntl.h>
#include <stdio.h>
int wmain (int argc, wchar_t** argv) {
_setmode(_fileno(stdout), _O_WTEXT);
wprintf(L"%s\n", argv[1]);
return 0;
}
It can also be done with GetCommandLineW; here is a simple version of the code
found at the HandBrake repo:
#include <stdio.h>
#include <windows.h>
int get_argv_utf8(int* argc_ptr, char*** argv_ptr) {
int argc;
char** argv;
wchar_t** argv_utf16 = CommandLineToArgvW(GetCommandLineW(), &argc);
int i;
int offset = (argc + 1) * sizeof(char*);
int size = offset;
for (i = 0; i < argc; i++)
size += WideCharToMultiByte(CP_UTF8, 0, argv_utf16[i], -1, 0, 0, 0, 0);
argv = malloc(size);
for (i = 0; i < argc; i++) {
argv[i] = (char*) argv + offset;
offset += WideCharToMultiByte(CP_UTF8, 0, argv_utf16[i], -1,
argv[i], size-offset, 0, 0);
}
*argc_ptr = argc;
*argv_ptr = argv;
return 0;
}
int main(int argc, char** argv) {
get_argv_utf8(&argc, &argv);
printf("%s\n", argv[1]);
return 0;
}
Since you're using MinGW (actually MinGW-w64, but that shouldn't matter in this case), you have access to the Windows API, so the following should work for you. It could probably be cleaner and actually tested properly, but it should provide a good idea at the least:
#define _WIN32_WINNT 0x0600
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#include <windows.h>
int main (void)
{
int argc;
int i;
LPWSTR *argv;
argv = CommandLineToArgvW(GetCommandLineW(), &argc);
if (argv == NULL)
{
FormatMessageA(
(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS),
NULL,
GetLastError(),
0,
(LPWSTR)&error, 0,
NULL);
fprintf(stderr, error);
fprintf(stderr, "\n");
LocalFree(error);
return EXIT_FAILURE;
}
for (i = 0; i < argc; ++i)
wprintf(L"argv[%d]: %ls\n", i, argv[i]);
// You must free argv using LocalFree!
LocalFree(argv);
return 0;
}
Bear in mind this one issue with it: Windows will not compose your strings for you. I use my own Windows keyboard layout that uses combining characters (I'm weird), so when I type
example -o àlf
in my Windows Command Prompt, I get the following output:
argv[0]: example
argv[1]: -o
argv[2]: a\u0300lf
The a\u0300 is U+0061 (LATIN SMALL LETTER A) followed by a representation of the Unicode code point U+0300 (COMBINING GRAVE ACCENT). If I instead use
example -o àlf
which uses the precomposed character U+00E0 (LATIN SMALL LETTER A WITH GRAVE), the output would have differed:
argv[0]: example
argv[1]: -o
argv[2]: \u00E0lf
where \u00E0 is a representation of the precomposed character à represented by Unicode code point U+00E0. However, while I may be an odd person for doing this, Vietnamese code page 1258 actually includes combining characters. This shouldn't affect filename handling ordinarily, but there may be some difficulty encountered.
For arguments that are just strings, you may want to look into normalization with the NormalizeString function. The documentation and examples linked in it should help you to understand how the function works. Normalization and a few other things in Unicode can be a long journey, but if this sort of thing excites you, it's also a fun journey.
Try compiling and running the following program:
#include <stdio.h>
int main()
{
int i = 0;
for( i=0; i<256; i++){
printf("\nASCII Character #%d:%c ", i, i);
}
printf("\n");
return 0;
}
In your output you should see those little question marks from number 128 and onward. FYI I am using Ubuntu, and when I compile and run this program (whith GNOME Terminal) this happens to me as well.
However, if I go to Terminal > Set character encoding... and select Western (WINDOWS-1252) as opposed to Unicode (UTF-8), and rerun the program, the extended ASCII characters display properly.
I don't know the exact steps for Windows/MinGW, but, in short, changing the character encoding should fix your problem.

Can someone help me understand how to allocate properly in c?

I don't think I properly understand how to allocate memory for what I want to do.
I would like my program to store arguments from the command line into an array of stucts called Command which has char **args in it. for example if I run
./test.c echo hello : ls -l
I want it to store it as this
commands[0].args[0]= echo
commands[0].args[1]= hello
commands[1].args[0]= ls
commands[1].args[1]= -l
But instead my code is storing it in this way
commands[0].args[0]= echo
commands[0].args[1]= hello
commands[0].args[2]= ls
commands[0].args[3]= -l
commands[1].args[0]= ls
commands[1].args[1]= -l
Could someone help me understand why it is storing ls -l in 2 places? Here is my code:
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
typedef struct test {
char **args;
} Command;
int main(int argc, char *argv[])
{
int i, j, k;
Command *commands;
j = k = 0;
commands = (Command *)malloc(argc * sizeof(Command));
for (i = 1; i < argc; i++)
{
if (strcmp(argv[i], ":") == 0)
{
j++;
k = 0;
}
else {
commands[j].args = (char **)realloc(commands[j].args, (k+1) * sizeof(char*));
commands[j].args[k++] = argv[i];
}
}
for (i = 0; i <= j; i++)
{
for (k = 0; k < 5; k++)
{
printf("commands[%d].args[%d]= %s\n", i, k, commands[i].args[k]);
}
}
return EXIT_SUCCESS;
}
Your data storage structure has no way of telling how many strings in commands[j] are valid. So I think it's putting two pointers each in commands[0] and commands[1] just like you expect. But then your print loop looks at commands[0].args[k] for k all the way up to 4, even though it's only valid to look at the first two. When you get up to looking at commands[0].args[2], the result is undefined. (Showing memory from somewhere else in your program, crashing, and catching fire are just a few of the things a program is allowed to do if you use undefined behavior.)
To figure out how many arguments are in each command, you could add a counter member to your struct test. Or maybe allocate one more pointer than there are arguments, and put a NULL after the last argument.
Here is how I would allocate the memory:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
typedef struct cmd_s {
int num;
char **args;
} cmd_t;
void print_cmds(cmd_t *c, int num) {
int i, j;
for (i=0;i<=num;i++) {
for (j=0;j<c[i].num;j++)
printf("cmds[%d][%d] = %s\n", i, j,c[i].args[j]);
}
}
int main(int argc, char *argv[]) {
int i, j = 0, k = 0;
cmd_t *cmds;
cmds = (cmd_t *)malloc(sizeof(cmd_t));
cmds[0].args = NULL;
cmds[0].num = 0;
for (i=1;i<argc;i++) {
if (strcmp(argv[i], ":") == 0) {
cmds = (cmd_t *)realloc(cmds, (sizeof(cmd_t) * ++j) + 1);
cmds[j].args = NULL;
cmds[j].num = 0;
continue;
}
cmds[j].args = (char **)realloc(cmds[j].args, sizeof(char *) * ++cmds[j].num);
cmds[j].args[cmds[j].num-1] = (char *)malloc(50);
strcpy(cmds[j].args[cmds[j].num-1], argv[i]);
}
print_cmds(cmds, j);
for (i=0;i<=j;i++) {
for(k=0;k<cmds[i].num;k++)
free(cmds[i].args[k]);
free(cmds[i].args);
}
free(cmds);
return 0;
}
Each of your Command structs only have one arg
Perhaps you should consider
typedef struct test {
char **args[5];
} Command;
and then design a better data structure, like a list of lists.
Perhaps you should store the length of args in the struct?
typedef struct test {
char ** args;
unsigned length;
} Command;
Also, maybe you should consider using some of the built in functionality of the C string library. For example, strtok splits a string using the delimiters you give it.

Resources