I am not very experienced in C. I am trying to have some code that works like this:
Declare array of strings;
Function that erases array of strings
and inserts a new set of strings (number unknown)
How can I do this? I know I can do const char *a[2]; but that requires entering an array size when I declare it. Can I make a variable for my string array that can support multiple sizes?
You can use pointers to pointers.
char **strings;
Here is how you would create it: (where <size> is the size of the array)
strings = malloc(sizeof(char*) * <size>);
Now setting/getting elements is pretty simple:
strings[0] = "hello";
printf("%s", strings[0]);
Just a warning, the memory is not already set to fully null strings. If you want all of the strings to be empty by default then use calloc() instead of malloc():
strings = calloc(sizeof(char*) , <size>);
You can control array size like this:
int size;
char *a[size];
printf("enter size");
scanf("%d",&size);
You have to use a char**, a pointer to pointer to char, to by able to capture a dynamic array of strings.
If you want 10 strings, you have to use:
char** strings = (char**)malloc(sizeof(char*)*10);
To store a string in the first element of the array, you have to use:
strings[0] = malloc(strlen("abcd")+1);
strpcy(strings[0], "abcd");
Here's a program that demonstrates the whole thing:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main()
{
char string[200];
char** strings = NULL;
int numStrings = 0;
int n = 0;
int i = 0;
/* Read the number of strings */
do
{
printf("Enter the number of strings (0 or higher): ");
n = scanf("%d", &numStrings);
} while ( n != 1 || numStrings < 0 );
/* Eat up the remaining characters afte the integer */
fgets(string, 199, stdin);
if ( numStrings > 0 )
{
/* Read the strings */
strings = (char**)malloc(numStrings*sizeof(char*));
for ( i = 0; i != numStrings; ++i )
{
printf("Enter a string: ");
fgets(string, 199, stdin);
strings[i] = malloc(strlen(string)+1);
strcpy(strings[i], string);
}
/* Print the strings back */
for ( i = 0; i != numStrings; ++i )
{
printf("%s", strings[i]);
}
/* Now release the memory back to the system */
/* First the individual strings */
for ( i = 0; i != numStrings; ++i )
{
free(strings[i]);
}
/* Now the array */
free(strings);
}
return 0;
}
Related
I am checking if a function returns true, it prints out valid strings according some other function I got. At the moment, it's printing it out correctly but it is also printing empty lines which seem to correspond to the invalid strings.
How can I make these empty lines go away?
Here is my code:
int main()
{
int i, count = 0;
char input[10];
char validStr[10][60] = {""};
for (i = 0; i < 60; ++i){
if(fgets(input,10, stdin) == NULL){
break;
}
input[strcspn(input,"\n")] = '\0';
if(checkIfValid(input)){
memcpy(validStr[i],input,sizeof(input));
count++;
}
}
printf("%d\n",count);
for (int j = 0 ; j < count; ++j){
printf("%s\n",validStr[j]);
}
}
The count indicates it is printing only the valid strings but as you can tell by the pic it prints white lines.
Note: For various reasons the program needs to follow the current order so the output is printed after the first for loop.
Thanks in advance!
Instead of this:
if(checkIfValid(input)){
memcpy(validStr[i],input,sizeof(input));
count++;
}
This:
if(checkIfValid(input)){
memcpy(validStr[count],input,sizeof(input));
count++;
}
As others have pointed out in the comments, you want to safely secure that string copy. May I suggest:
if(checkIfValid(input)){
char* dst = validStr[count];
size_t MAXLEN = 10;
strncpy(dst, input, MAXLEN);
dest[MAXLEN-1] = '\0';
count++;
}
Continuing from the comment, if you want to store the entire string, you need to provide adequate space for the nul-terminating character.
AAAAAAAAAA
QELETIURTE
...
contain strings that are 10 characters long and will not fit in input as declared char[10].
Instead of looping with a for, allow the return from fgets() control your read-loop and keep count as a condition controlling the loop to ensure you protect your array bounds, e.g.
#include <stdio.h>
#include <string.h>
#define MAXC 128 /* if you need a constant, #define one (or more) */
#define NSTR 10
int checkIfValid (const char *s) { return 1; (void)s; }
int main(void)
{
size_t count = 0;
char input[MAXC];
char validStr[NSTR][MAXC] = {""};
while (count < NSTR && fgets (input, sizeof input, stdin)) {
input[strcspn(input,"\n")] = '\0';
if(checkIfValid(input)){
strcpy (validStr[count], input);
count++;
}
}
printf ("%zu\n",count);
for (size_t j = 0 ; j < count; ++j) {
printf("%s\n",validStr[j]);
}
}
(adjust your array declaration for 60 strings of 10 characters each)
If you want to cut off at 9 characters and ensure the stings are nul-terminated, #selbie has that covered.
Example Use/Output
With your data (as good as I could read it) in dat/validstr.txt you could do:
$ ./bin/validstring <dat/validstr.txt
6
AAAAAAAAAA
QELETIURTE
321qweve
sdsdsdfFF
GRSGGFDDSS
toLotssAAA
I need to write a C function that gets from the user the number of the words that he wants to enter, then the function has to scan the word from the user and but them in the array.
For example:
Program:
number of words:
User:
3
hi
my
name
(between every word there is enter) then the function has to put these words in
string array (the size of the array must be defined by malloc and the max size of the string is 100 (could be less)).
int main()
{
int n;
printf("Please enter the number of words: \n");
if (scanf("%d",&n)!=1)
return 0;
char *name;
name = malloc((sizeof(char)*100*n));
int c;
int i;
int m;
for (i = 0; i < n && ((c=getchar()) != EOF );i++)
{
name[i] = c;
}
finds_themin(&name, m); //I know this work
return 0;
}
You need to setup a pointer to pointer.
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main(){
char **s;
int n;
char buffer[64];
fgets(buffer,64,stdin);
n=strtol(buffer,NULL,10);// I avoid using scanf
s=(char **)malloc(sizeof(char*)*n);// you need to declare a pointer to pointer
/*
'PtP s' would look like this:
s[0]=a char pointer so this will point to an individual string
s[1]=a char pointer so this will point to an individual string
s[2]=a char pointer so this will point to an individual string
....
so you need to allocate memory for each pointer within s.
*/
int i;
for(i=0;i<n;i++){
s[i]=(char*)malloc(sizeof(char)*100);// length of each string is 100 in this case
}
for(i=0;i<n;i++){
fgets(s[i],100,stdin);
if(strlen(s[i])>=1){// to avoid undefined behavior in case of null byte input
if(s[i][strlen(s[i])-1]=='\n'){ // fgets also puts that newline character if the string is smaller than from max length,
s[i][strlen(s[i])-1]='\0'; // just removing that newline feed from each string
}
else{
while((getchar())!='\n'); //if the string in the command line was more than 100 chars you need to remove the remaining chars for next fgets
}
}
}
for(i=0;i<n;i++){
printf("\n%s",s[i]);
}
for(i=0;i<n;i++){
free(s[i]); //avoiding leaks
}
free(s);
}
As you need to store an array of strings you need an array of char* or char** to point each string (char array).
char **name;
name = malloc(n); // to store n strings.
Then in the loop use fgets to read the input as a line. Also, you need to allocate the memory for each new char array.
fflush(stdin);
for (i = 0; i < n; i++) {
name[i] = malloc(100); // allocating memory for string.
fgets (name[i], 100, stdin); // 100 is the max len
}
You can then simply iterate over the char** array, the ith index will point to the ith string.
for (i = 0; i < n; i++) {
// printf("%s", name[i]);
}
This program is supposed to dynamically store each string entered into a pointer. Each pointer is part of an array of pointers that will collectively hold all of the strings. When the user enter an empty word, or NULL, it is supposed to quit. My problem is that the code just skips over the NULL conditional statement. I saw some similar posts and have been at it for hours but just can't solve it.
#include <stdio.h>
#include <string.h>
void readWord(char wordChar[], int MAX_CHARS);
int main()
{
int MAX_CHARS = 20;
int wCount = 0;
char *wordArray[wCount]; // Array of pointers that will each point to wordChar
char wordChar[MAX_CHARS];
int i;
for(i = 0;;i++)
{
wCount++;
printf("Enter word: ");
readWord(wordChar, MAX_CHARS); //Reads one word at a time
//Dynamically store each
wordArray[i] = (char*) malloc((int) strlen(wordChar) * (int) sizeof(char));
wordArray[i] = wordChar;
printf("%s \n", wordArray[i]); //Troubleshooting *********************
// If loop ends scanning when word is NULL
if(wordArray[i] == 'NULL')
{
printf("if loop");
break;
}
else printf("no loop");
}
}
/***********************************************************/
void readWord(char wordChar[], int MAX_CHARS)
{
int letter, i = 0;
while((letter = getchar()) != '\n')
{
if(i < MAX_CHARS)
{
wordChar[i] = letter;
i++;
}
}
wordChar[i] = '\0';
}
The short and useless summary is: you're #includeing string.h; use it!
You're trying to compare two pointers directly.
if(wordArray[i] == 'NULL')
This line looks at the pointer value of wordArray[i] to the value of the multi-character literal 'NULL' (note that I didn't say string: you used single quotes here, so 'NULL' has the integer value 0x4e554c4c; see https://stackoverflow.com/a/7459943/510299). If wordArray[i] points to the address 0x12345678, then this is comparing 0x12345678 to 0x4e554c4c and sees that they're not equal.
What you want is to compare strings. In C, you can't do this with == because C strings are char arrays or pointers to chars; == compares the pointer (address) value, as I noted above.
Solution, use strcmp.
if(strcmp(wordArray[i], "NULL") == 0)
(Note the use of double quotes.)
EDIT: Also note that char *wordArray[wCount]; is declared when wCount == 0. This nominally means you tried to declare an array of length 0, which is undefined behaviour. You need to declare wordArray with some length (probably the maximum number of words you can store). [Thanks to riodoro1 for pointing this out in a comment.]
You made a similar blunder with string manipulation in C here:
wordArray[i] = (char*) malloc((int) strlen(wordChar) * (int) sizeof(char));
This line sets the pointer wordArray[i] to some newly allocated memory.
wordArray[i] = wordChar;
This line then proceeds to change the pointer wordArray[i] to point to the original location where the read word was stored. Oops. The next time you go through this loop, wordChar changes, and wordArray[i] is pointing to wordChar... so the new word "replaces" all the previous words.
Solution? You need to copy the string to the memory you just malloc'd. Use strcpy().
printf("if loop");
A conditional (if) statement is not a kind of loop.
#include <stdio.h>
#include <stdlib.h> //for realloc and free (malloc)
#include <string.h>
void readWord(char wordChar[], int MAX_CHARS);
int main(void){
int MAX_CHARS = 20;
int wCount = 0;
char **wordArray = NULL; // Array of pointers that will each point to wordChar
char wordChar[MAX_CHARS];
int i;
for(i = 0;;i++){
printf("Enter word: ");
readWord(wordChar, MAX_CHARS); //Reads one word at a time
if(*wordChar == '\0' || strcmp(wordChar, "NULL") == 0){//empty word or "NULL"
putchar('\n');
break;
}
wCount++;
wordArray = realloc(wordArray, wCount * sizeof(*wordArray));//check omitted
//Dynamically store each
wordArray[i] = malloc(strlen(wordChar) + 1);//+1 for NUL
strcpy(wordArray[i], wordChar);//copy string
}
//check print and free
for(i = 0; i < wCount; ++i){
printf("'%s'\n", wordArray[i]);
free(wordArray[i]);
}
free(wordArray);
return 0;
}
void readWord(char wordChar[], int MAX_CHARS){
int letter, i = 0;
while((letter = getchar()) != '\n' && letter != EOF){
if(i < MAX_CHARS -1)//-1 for NUL, or char wordChar[MAX_CHARS+1];
wordChar[i++] = letter;
else
;//drop letter upto newline
}
wordChar[i] = '\0';
}
Wondering how store different strings in an array.
For example a user would input 'qwe' and the program would then store that in an array variable[0]. Entering another string would then store it as variable[1] and so on
int
main(int argc, char *argv[]) {
char variable[1000];
int i;
printf("enter a variable\n");
scanf("%s", variable);
for (i = 0; ??? ;i++) {
printf("The variable entered was: %s\n",variable[i]);
}
return 0;
Im new to C so I have no idea what im doing. but thats what I have came up with so far and was wondering if I could get some help with filling in the rest
Thanks!
You can use 2D array to store multiple strings. For 10 strings each of length 100
char variable[10][100];
printf("Enter Strings\n");
for (int i = 0; i < 10 ;i++)
scanf("%100s", variable[i]);
Better to use fgets to read string.
fgets(variable[i], sizeof(variable[i]), stdin);
You can also use dynamic memory allocation by using an array of pointers to char.
The most efficient way is to have an array of character pointers and allocate memory for them as needed:
char *strings[10];
int main(int ac, char *av[]) {
memset(strings, 0, 10 * sizeof(char *));
for (int i = 0; i < 10; i += 1) {
char ins[100];
scanf("%100s", ins);
strings[i] = malloc(strlen(ins) + 1);
if (strings[i]) {
strcpy(strings[i], ins);
}
}
}
variable[0] has just stored first letter of string. If you want to store multiple strings in an array you can use 2D array.
it has structure like
arr[3][100] = { "hello","world", "there"}
and you can access them as
printf("%s", arr[0]); one by one.
scanf returns number of successful readed parameters;
use 2D array for string-array
Never go out of bounds array
#include <stdio.h>
//Use defines or constants!
#define NUM_STRINGS 10
#define MAX_LENGTH_OFSTRING 1000
int main() {
char variable[NUM_STRINGS][MAX_LENGTH_OFSTRING +1 /*for '\0' Null Character */];
int i = 0;
printf("enter a variable\n");
while(scanf("%s", variable[i]) > 0){//if you print Ctrl+Z then program finish work. Do not write more than MAX_LENGTH_OFSTRING symbols
printf("The variable entered was: %s\n",variable[i]);
i++;
if(i >= NUM_STRINGS)
break;
}
return 0;
}
I am having trouble storing strings into a 2d array using scanf.
To illustrate, this is the input the program accepts:
p2/src/stuff:5:
p3/src/stuff:5:
p4/src/stuff:6:
So I want to be able to split the strings and numbers by colons and store them separately. So ideally, my 2d array would look like this for strings:
[["p2/src/stuff"], ["p3/src/stuff"], ["p4/src/stuff"]]
Numbers can be stored in a 1d array.
Here is what I have so far:
int main() {
char *str;
char *i;
int n = 1;
while (n == 1) {
n = scanf("%m[^':']:%m[^':']:", &str, &i);
}
printf("# inputs read: %d\n", n);
printf("%s\n", str);
printf("%s\n", i);
}
Here it only prints the first line:
p2/src/stuff
5
Should I have an iterator that dose pointer arithmetic? I'm not familiar with pointer arithmetic.
scanf returns the number of items scanned. In this case it would be 2 instead of 1. Here a return of 1 would indicate a problem during the scan.
The %m specifier allocates memory to the pointers. Using a single pair of pointers, they should be freed in eadh iteration of the loop. You could use an array of pointers to store each of the inputs.
The scanset does not need the single quotes [^':']. If you are scanning for all characters that are not a colon [^:] will work.
EOF will terminate the while loop so if you are reading from a file, it will stop at the end of the file. Reading from stdin could be terminated using Ctrl+D (Linux) or Ctrl+Z (Windows).
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main() {
char *str;
char *i;
int n;
while ( ( n = scanf("%m[^:]:%m[^:]:", &str, &i)) == 2) {
printf("# inputs read: %d\n", n);
printf("%s\n", str);
printf("%s\n", i);
free ( str);
free ( i);
}
return 0;
}
EDIT:
This uses an array of pointers to collect several inputs to the str and i arrays.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main() {
char *str[10];// array of pointers
char *i[10];
int each = 0;
int loop = 0;
int n = 0;
while ( ( n = scanf("%m[^:]:%m[^:]:", &str[each], &i[each])) == 2) {
printf("# inputs read: %d\n", n);
printf("%s\n", str[each]);
printf("%s\n", i[each]);
each++;
if ( each > 9) {
break;//too many inputs for array size
}
}
for ( loop = 0; loop < each; loop++) {
printf ( "str[%d]=%s\n", loop, str[loop]);//print all the str inputs
}
for ( loop = 0; loop < each; loop++) {
printf ( "i[%d]=%s\n", loop, i[loop]);//print all the i inputs
}
for ( loop = 0; loop < each; loop++) {//free memory
free ( str[loop]);
free ( i[loop]);
}
return 0;
}
You have a few issues here.
First, while you should be using character pointers, you never allocate any memory for them. Next, when you use scanf, you should not be passing the address of the pointers but the pointers themselves. This is an easy mistake to make since you must pass the address when using scanf with integer types.
int main() {
char str[255];
char i[255];
int n = 1;
while (n == 1) {
n = scanf("%m[^':']:%m[^':']:", str, i);
}
printf("# inputs read: %d\n", n);
printf("%s\n", str);
printf("%s\n", i);
}