This is part of an assignment, so the instructions are clear and I'm not allowed to use anything other than what is specified.
The idea is simple:
1) Create an array of structs which hold a string and a count
2) Count the occurrence of the string in each struct and store the count in that struct
3) Print the strings and their number of occurrences
I have been explicitly told to use the fgets and strstr functions
Here is what I've got so far,
#define MAX_STRINGS 50
#define LINE_MAX_CHARS 1000
int main(){
int n = argc - 1;
if (n > MAX_STRINGS) {
n = MAX_STRINGS;
}
Entry entries[MAX_STRINGS];
char **strings = argv+1;
prepare_table(n, strings, entries);
count_occurrences(n, stdin, entries);
print_occurrences(n, entries);
}
void prepare_table (int n, char **strings, Entry *entries) {
// n = number of words to find
// entries = array of Entry structs
for (int i = 0; i < n; i++){
Entry newEntry;
newEntry.string = *(strings + 1);
newEntry.count = 0;
*(entries + i) = newEntry;
}
}
void print_occurrences (int n, Entry *entries) {
for (int i = 0; i < n; i++){
printf("%s: %d\n", (*(entries + i)).string, (*(entries + i)).count);
}
}
void count_occurrences (int n, FILE *file, Entry *entries) {
char *str;
while (fgets(str, LINE_MAX_CHARS, file) != NULL){
for (int i = 0; i < n; i++){ // for each word
char *found;
found = (strstr(str, (*(entries + i)).string)); // search line
if (found != NULL){ // if word found in line
str = found + 1; // move string pointer forward for next iteration
i--; // to look for same word in the rest of the line
(*(entries + i)).count = (*(entries + i)).count + 1; // increment occurrences of word
}
}
}
}
I know for a fact that my prepare_table and print_occurrences functions are working perfectly. However, the problem is with the count_occurrences function.
I've been given a test file to run which just tells me that I'm not producing the correct output. I can't actually see the output to figure out whats wrong
I'm new to pointers, so I'm expecting this to be a simple error on my part. Where is my program going wrong?
fgets(char * restrict str, int size, FILE * restrict stream) writes into the buffer at str... but you don't have a buffer at str. What is str? It's just a pointer. What's it pointing at? Garbage, because you haven't initialized it to something. So it might work or it might not (edit: by which I mean you should expect it not to work, and be surprised if it did, thank you commenters!).
You could fix that by allocating some memory first:
char *str = malloc(LINE_MAX_CHARS);
// do your stuff
free(str);
str = NULL;
Or even statically allocating:
char str[LINE_MAX_CHARS];
That's one problem I can see anyway. You say you don't have output, but surely you can add some debug statements using fprintf(stderr, "") at the very least..?
Related
I'm trying to get to read string input from user and store it in two dim array using pointers.
I'm getting Access violation reading location exception when trying to use those strings.
first I declared char*** that will store pointers for two dim array , then I use for loop to initial two dim array for each cell.
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define WORDLEN 80
#define DEFLEN 200
#define KEYVALUE 2
char*** MallocDic(int dictionarySize);
char** MallocDicElement(char* word, char* definition);
void PrintDictionary(char*** dictionary, int dictionarySize);
int main()
{
int dictionarySize;
printf("Please enter dictionary size\n");
scanf("%d", &dictionarySize);
char*** dictionary = MallocDic(dictionarySize);
int i;
for (i = 0; i < dictionarySize; i++) {
char* inputWord = (char*)malloc(WORDLEN * sizeof(char));
char* inputDef = (char*)malloc(DEFLEN * sizeof(char));
if (inputWord == NULL || inputDef == NULL)
{
printf("Failed to allocate memory!\n");
exit(1);
}
printf("enter word : \n");
scanf("%s", inputWord);
printf("enter definition : \n");
scanf("%s", inputDef);
printf("word : %s ,def : %s\n", inputWord, inputDef);
//dictionary[i] = MallocDicElement(inputWord, inputDef);
//free(inputDef);
free(inputWord);
}
printf("Print Dictionary : \n");
//PrintDictionary(dictionary, dictionarySize);
}
char*** MallocDic(int dictionarySize) {
char*** p;
p = (char***)malloc(dictionarySize * sizeof(char**));
return p;
}
char** MallocDicElement(char* word, char* definition) {
char** p = (char**)malloc(KEYVALUE * sizeof(char*));
int i;
for (i = 0; i < KEYVALUE; i++) {
if (i == 0) {
p[i] = (char*)malloc(WORDLEN * sizeof(char));
p[i] = word;
}
else {
p[i] = (char*)malloc(DEFLEN * sizeof(char));
p[i] = definition;
}
}
return p;
}
void PrintDictionary(char*** dictionary, int dictionarySize) {
int i = 0, j = 0;
for (i = 0; i < dictionarySize; i++) {
for (j = 0; j < KEYVALUE; j++) {
printf("word : %s\n", dictionary[i][0]);
printf("definition : %s\n", dictionary[i][1]);
}
}
}
The logic breaks in when trying to print the first string.
what am I missing here ?
Thanks for any help.
At least these problems.
Leaked memory
Code allocates memory and saves the pointer to that allocation to p[i] and then copies the pointer word to p[i] in the next line. This loses the pointer returned from malloc().
p[i] = (char*)malloc(WORDLEN * sizeof(char));
p[i] = word; // ???
Much more likely OP wants to copy the string, pointed to by word to the memory pointed to by p[i].
p[i] = malloc(WORDLEN);
strcpy(p[i], word);
More common to allocate only what is needed.
p[i] = malloc(strlen(word) + 1);
strcpy(p[i], word);
Research strdup().
Error checking omitted for brevity.
Do not use "%s", "%[]" without a width in *scanf()
Limit acceptable input to 1 less than the size of the destination array.
"%s" does not read and save spaces
The below will not work to read a definition that contains spaces.
printf("enter definition : \n");
scanf("%s", inputDef); // Stops after first word
Scanning will stop at the first white-space after reading some non-white-space.
Perhaps:
scanf(" %199[^\n]", inputDef);
Check return value of input functions
if (scanf(" %199[^\n]", inputDef) != 1) {
Handle_input_error();
}
Other:
Avoid hard to read & maintain allocation
Rather than cast (not needed) and size to the type (defined someplace else), allocate to the size of the referenced object - no type needed to get wrong.
// p = (char***)malloc(dictionarySize * sizeof(char**));
p = malloc(sizeof p[0] * dictionarySize);
Easier to code right, review and maintain.
At the risk of a non-answer here (not working with your extant code) I would like to suggest you take the time to better structure your data. Even something as simple as:
// A `dictionary` is an array of `capacity` entries, `size` of which are in use.
// Elements are kept in lexicographical order.
struct dictionary
{
struct entry
{
const char * word;
const char * definition;
};
struct entry * entries;
size_t size;
size_t capacity;
};
typedef struct dictionary dictionary;
This makes life about a bazillion times easier when dealing with stuff. You can now create a couple of useful functions:
dictionary * new_dictionary( size_t capacity );
void free_dictionary( dictionary * dict );
This structured nature makes it easier to manage individual parts. In particular, your users can pass the pointer to the dictionary around and never have to worry about it changing. For example, suppose you want to update the dictionary’s capacity:
void set_dicitionary_capacity( dictionary * dict, size_t new_capacity )
{
if (new_capacity < dict->size) return;
struct entry * new_entries = realloc( dict->entries, new_capacity * sizeof dict->entries[0] );
if (!new_entries) return;
dict->capacity = new_capacity;
dict->entries = new_entries;
}
This idea of having functions to interface with your opaque dictionary object is the basis for basic data encapsulation. Doing so makes the using code so much easier:
dictionary * words = new_dictionary( 1000 );
if (!words) fooey();
update_dictionary( words, "hello", "a greeting" );
update_dictionary( words, "world", "the Earth; a planet; any organism’s collective society" );
printf( "There are %zu words in the dictionary.\n", dictionary_size( words ) );
const char * desc = find_word( words, "there" );
printf( "Obi Wan can%s use this dictionary.\n", desc ? "" : "not" );
free_dictionary( words );
Hopefully we can already see how things are easier to grok on every level.
In other words, write code in such a way as to make meaning and structure as clear as possible. This helps to reduce the amount of failure our befuddled minds can generate when writing code.
I am currently trying to parse a string into an array of strings.
So far, I currently believe I've succeeded in splitting up the string by inserting '\0' after every word "chunk".
However, when I attempt to free the string array later, some of my words have the same byte address, and thus, when I try to free one of them, the other gets freed as well.
This is the code for my parser, I apologize for its messy form:
/*
* parser()
*
* Parses a given string into different words and returns a list with the words.
* If there is a non-space and non-alphabetic character an error is recorded.
*/
void parser(char* str, char** actualList, char** freeingList,char* error, int* length){
// initialize variables
bool chara = false;
bool beginning = true;
int size = strlen(str);
bool nonAlphaSpace = false;
// iterate through the entire string
for(int i = 0; i < size; i++){
// if the character is not either a space or an alphabetic character
if(isspace(str[i])==0 && isalpha(str[i])==0 && !nonAlphaSpace){
*error = str[i];
nonAlphaSpace = true;
}
}
// if there was no irregular character
if(!nonAlphaSpace){
for(int j = 0; j < size; j++){
// if the character is the beginning of the current string
if(beginning){
// record this string into the list of words
freeingList[*length] = &str[j];
(*length)++;
// set the status of any alphabetic character being present to false;
chara = false;
// if the current character is an alphabetic character
if(isalpha(str[j])!=0){
chara = true;
}
beginning = false;
}
// if the character is a space
else if(isspace(str[j])!=0){
// if there was a character beforehand
if(chara){
// get the pointer to the next character
char* new = &str[j+1];
// change the current character to a null
str[j] = '\0';
// realign the pointer to the string to rest of the string
str = new;
j = -1;
size = strlen(str);
beginning = true;
}
}
// if the character is an alphabetic character
else{
chara = true;
}
}
// if the last chunk of string left didn't contain any characters
if(!chara){
free(str);
}
// for every word extracted
for(int k = 0; k < *length; k++){
int newSize = strlen(freeingList[k]);
bool first = true;
// get the pointer to the first character in the word, i.e. not the first few spaces
for(int l = 0; l < newSize; l++){
if(isspace(freeingList[k][l])==0 && first){
actualList[k] = &freeingList[k][l];
first = false;
}
}
}
}
}
This is when I attempt to free it:
// free the current collection of strings
for(int j = 0; j < size; j+=2){
free(words[j]);
}
When I input "home or for" into the parser and later try to free it, the address of "home" is 0x7fffffffe840 while the address of "for" is 0x7fffffffe848. This leads me to believe that the freeing of home also frees or causing a SIGABRT error later.
Is this assumption correct? How can I overcome this double freeing?
You should only call free() on pointers returned by malloc(), calloc(), or realloc(). What it looks like you are doing:
char *ptr = malloc(100);
char *ptr2 = &ptr[10];
free(ptr2); // You can't do that.
I suspect you meant to make a copy of the strings. Here's a simplified version:
void parser(char* str, char** actualList, int* length) {
char *start = str; // The start of the current string
int count = 0; // Number of strings copied
while (*str) {
if (isspace(*str)) {
*str = '\0';
actualList[count] = malloc(strlen(start) + 1); // Allocate space for string
strcpy(actualList[count++], start); // Copy string
start = str + 1; // Reset for next string
if (count == *length - 1) break; // Don't overflow pointer array
}
str++;
}
// Grab the final string
actualList[count] = malloc(strlen(start) + 1); // Allocate space for string
strcpy(actualList[count++], start); // Copy string
*length = count;
}
Then call it like:
char input[] = "home or for";
char *words[5];
int max_words = 5;
parser(input, words, &max_words);
// max_words should be 3 now
for (int i = 0; i < max_words; i++) {
printf("%s\n", words[i]);
}
// Clean up
for (int i = 0; i < max_words; i++) {
free(words[i]);
}
Output:
home
or
for
That's not a parser, though. More a tokenizer.
#include <assert.h>
#include <errno.h>
#include <stddef.h>
#include <stdbool.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
bool parser(char const *str, char ***words, size_t *num_words, size_t *error)
{ // ^^^ gaaaah! *)
assert(words);
errno = 0;
size_t length = strlen(str);
for (size_t i = 0; i < length; ++i) {
if (!isalnum(str[i]) && !isspace(str[i])) {
*error = i; // the position is most likely more meaningful than the character
return false; // get outta here!!
}
}
char const *begin;
char const *end;
*num_words = 0;
*words = NULL;
bool in_word = false;
for (size_t i = 0; i <= length; ++i) {
if (!in_word && isalnum(str[i])) { // word begins
begin = str + i;
in_word = true;
}
else if (in_word && !isalnum(str[i])) { // word ended
end = str + i;
char *word = calloc(end - begin + 1, sizeof *word);
if (!word) {
for (size_t i = 0; i < num_words; ++i)
free((*words)[i]);
free(*words);
errno = ENOMEM;
return false;
}
memcpy(word, begin, end - begin);
char **tmp = realloc(*words, (*num_words + 1) * sizeof *tmp);
if (!tmp) {
free(word);
for (size_t i = 0; i < num_words; ++i)
free((*words)[i]);
free(*words);
errno = ENOMEM;
return false;
}
*words = tmp;
tmp[(*num_words)++] = word;
in_word = false;
}
}
return true;
}
int main(void)
{
char const *foo = "slfkja askdfj jk j aksjf lasjdflkjsdlf jask fdjl";
char **words = NULL;
size_t num_words = 0;
size_t error = 0;
if (!parser(foo, &words, &num_words, &error)) {
if (errno == ENOMEM)
fputs("Not enough memory. :(\n\n", stderr);
else fprintf(stderr, "Error at position %zu: \"%s\"\n\n", error, foo + error);
return EXIT_FAILURE;
}
puts("List of words:");
for (size_t i = 0; i < num_words; ++i) {
printf("\"%s\"\n", words[i]);
free(words[i]);
}
free(words);
}
C should be renamed brainf*ck ...
*) Three Star Programmer
you modify the value of str in the body of the function (in the line str = new; (don't use new as an identifier, more if you plan to use this code as C++ code, as new is a reserved word in C++). As you don't call malloc(3) in the function body, it's quite normal you get a problem from free(3), as free requires to be passed a pointer previously generated with malloc (and only once, so you cannot call it twice with the same pointer). This is the reason of you getting SIGABRT and the like. As a general rule, don't call free(3) in a function you don't also call malloc for the same pointer. That use is error prone and you will run into trouble more than once a day if you insist in doing everything in a single function.
better than apologize for the messy form of the code, please, clean it before posting. Post a minimu (meaning the minimum code that shows the error), full (meaning that we can compile it and observe the result you post as failing), verifiable (code that shows it producing the observed result, and not the expected one) and complete (this means we have nothing to do but compile it and run) code (so we can test it failing as you say, without having to correct it first) That way, we can make a diagnostic of what happens in your code. If we need to correct the code just to make it runnable, we can correct the main problem you are observing and be unable to see the mistake. You see? :)
Note about using new as an identifier in C code:
Many Unit Testing frameworks require your code to be compilable as C++ code, so it can be used by the framework (at least Google Test requires this) If you plan to write unit tests for your code, remember that new is a reserved word in C++ for the operator new, and so, your code will produce syntax errors if you try to compile it with a c++ compiler. Better if you don't use it.
I tried many solution for this issue, but none worked properly!
I want to copy value of char** array to a variable of type char*.
char *line;
char **tokens = malloc(....);
So, I tried the following:
for(i=0; i < sizeof(tokens); i++)
strncpy(line, tokens[i], strlen(line));
Or
for(i=0; i < sizeof(tokens); i++)
strncat(line, tokens[i]);
Or
for(i=0; i < sizeof(tokens); i++)
memcpy(line, tokens[i], strlen(line));
My understanding is that tokens[i] would be of type char*, but what I couldn't understand if the error I'm getting.
Segmentation fault (core dumped)
If these ways won't work, how can I do the copying?
Any hints?
char *removesubString(char *path, char **args){
char *dir;
int COUNT;
COUNT = 100;
char **dirs = malloc(sizeof(char*)*COUNT);
int i, position;
for (i = 2; i < sizeof(args); i++) {
if(args[i] == NULL){
break;
}
dir = strtok(path, PATH_DELIM);
position = 0;
while (dir != NULL) {
if(strcmp(dir, args[i]) == 0){
dir = strtok(NULL, PATH_DELIM);
continue;
}
dirs[position] = dir;
position++;
dir = strtok(NULL, PATH_DELIM);
}//end of while
dirs[position] = NULL;
}//end of for
char *line;
line = "";
for (i = 0; i < position; i++) {
strncpy(line, dirs[i], strlen(dirs[i]));
}
return line;
}
The first issue that pops up about your code is that you're wrong with the boundaries:
char *line;
char **tokens = malloc(TOKENS_ARRAY_SIZE);
when you do:
for(i=0; i < sizeof(tokens); i++) {
…
}
it's not returning the size of the allocated memory, but the allocated memory for the tokens pointer itself. From the sizeof manpage:
Returns the size, in bytes, of the object representation of type
It happens that when you do sizeof on a static matrix, it will return the size of the matrix because that's the amount of allocated memory for it. But for a dynamically allocated matrix, it will only return the size of the pointer, i.e. if you do:
char array_static[42];
char* array_dyn = malloc(sizeof(char)*42);
printf("sizeof(array_static) = %d\n", sizeof(array_static));
printf("sizeof(array_dyn) = %d\n", sizeof(array_dyn));
it will return:
sizeof(array_static) = 42
sizeof(array_dyn) = 8
so if the number of items within your dynamic array is less than the returned size of the array's pointer, you'll overflow and you'll get a segfault.
So the right way to handle your situation, is to keep the length of the dynamic array in another variable, update it as you're setting up the size of the allocated memory, and then use that value for iterations.
int tokens_length = 42;
char *line;
char **tokens = malloc(sizeof(char*)*tokens_length);
for(i=0; i < sizeof(tokens_length); i++) {
…
}
so in your case, you should be doing:
// keep somewhere the number of directories that you *can* allocate
int nb_dirs = 100;
char **dirs = malloc(sizeof(char*) * nb_dirs);
…
// keep a pointer on how many directories you've added
int position = 0;
while (dir != NULL) {
…
position++;
// fail loudly if you're adding more directories than you've allocated
// or you might use realloc() to extend the array's length
if (position >= nb_dirs) {
printf("ERROR! Too many directories!");
// RETURN WITH ERROR!
}
…
}
// here you iterate over all the directories you've added
for(i = 0; i <= position; i++){
// here you can do stuff with dirs, and copy only the length of the dirs element
strncpy(<TARGET>, dirs[i], strlen(dirs[i]);
}
Then there's another issue you should think about: in your loop, you're modifying path, given as an argument, where you're strcpy()ing dirs into:
strncpy(path, dirs[i], <LENGTH>);
But that makes little sense, whatever you're trying to do is not what you've written.
Here, considering that the size argument is correctly set, you'd be copying each item of the dirs array into the same variable. So you'd end up having always the last value of the dirs array referenced at the path pointer.
But the issue is that you only have the path pointer, but you know little about how it has been allocated when it's been given to the function. How has it been allocated, and how much memory was allocated? What "useful" size is it (though that one can be guessed with strlen())?
Oh, and finally, don't forget to free() your allocations once you're done with them. Do not leak memory, that's rude! ☺
edit:
ok, here are stuff I can see that are wrong, and some comments about it:
char *removesubString(char *path, char **args){
char *dir;
int COUNT = 100;
char **dirs = malloc(sizeof(char*)*COUNT);
int i, position;
/* for both XXX marks below:
*
* below, sizeof(args) will return the size of the pointer
* not the number of items it contains. You *NEED* to pass
* a "int argc" as parameter to your function, that gives
* the numbers of items in the array.
* Think about why you have argc in the main() function construct:
* int main(int argc, const char** argv)
* _OR_ if the args array of strings is _ALWAYS_ terminated
* by a NULL item, then you should do: */
// int i = 0;
// while(args[i] != NULL) {
// /* do stuff */
// ++i;
// }
for (i = 2; i < sizeof(args) /* XXX */; i++) {
if(args[i] == NULL){ /* XXX */
break;
}
dir = strtok(path, PATH_DELIM);
position = 0;
while (dir != NULL) {
if(strcmp(dir, args[i]) == 0){
dir = strtok(NULL, PATH_DELIM);
continue;
}
/* because within the function you have no guarantee
* on the number of tokens within path, if you have
* more than 100 tokens, you will overflow the dirs array.
* a good idea would be to test whether position is bigger
* than or equal to COUNT, and if it is use realloc to
* extend dirs */
dirs[position] = dir;
position++;
dir = strtok(NULL, PATH_DELIM);
/* you could avoid having twice the former line
* and instead make your loop body being: */
// while (dir != NULL) {
// if(strcmp(dir, args[i]) != 0){
// /* TODO: check position vs COUNT and realloc dirs if necessary */
// dirs[position] = dir;
// ++position;
// }
// dir = strtok(NULL, PATH_DELIM);
// }
}
dirs[position] = NULL;
}
char *line;
line = ""; /* ← here you allocate line with a string of length 1 */
for (i = 0; i < position; i++) {
// so here, you'll write up to the number of characters
// within dirs[i], into a string of length one.
strncpy(line, dirs[i], strlen(dirs[i]));
}
/* And even if it was working you'd be assigning the line
* variable to a new value at each iteration, ending up doing
* something equivalent to the following line, but with "position"
* numbers of iterations: */
// strncpy(line, dirs[position-1], strlen(dirs[position-1]));
/* Don't forget to free the instances you've allocated dynamically
* before leaving the function: */
// free(dirs);
/* And finally there's another issue here, you're returning
* a variable that has been statically allocated above, so that
* when you'll try to use the pointed instance in the calling
* context, that variable won't exist anymore. */
return line;
}
HTH
Here is my code
//Split up the config by lines
int x;
int numberOfConfigLines = 0;
for (x = 0; x < strlen(buffer); x++)
{
if (buffer[x] == '\n') {
numberOfConfigLines++;
}
}
char *configLines[numberOfConfigLines];
tokenize(configLines, buffer, "\n", numberOfConfigLines);
The idea of this function is to count the amount of newlines in a buffer, then split the buffer into a strtok array using this:
#include <string.h>
#include <stdlib.h>
void tokenize(char **arrToStoreTokens, char *delimitedString, char *delimiter, int expectedTokenArraySize) {
//Create a clone of the original string to prevent making permanent changes to it
char *tempString = (char *)malloc(strlen(delimitedString) + 1);
strcpy(tempString, delimitedString);
if (expectedTokenArraySize >= 1) {
arrToStoreTokens[0] = strtok(tempString, delimiter);
int x;
for (x = 1; x < expectedTokenArraySize; x++ ) {
arrToStoreTokens[x] = strtok(NULL, delimiter);
}
}
//Dispose of temporary clone
free(tempString);
}
If I access arrToStoreTokens[0] directly, I get the correct result, however when I try to access configLines[0] once thetokenize function has ended, I get different results (can be unknown characters or simply empty)
Additionally, I believe this has only started occurring once I began running the program as root (for a different requirement) - I may be wrong though. - EDIT: Confirmed not to be the problem.
Any ideas?
strtok doesn't reallocate anything. It only makes cut and pointers of what you gave to it.
Your array stores pointers that strtok gives you, but don't copy contents.
So if you free your tempString variable, you free data that was pointed by return values of strtok. You have to keep it and free it only at the end.
Or you can make a strdup of each return of strtok to store it in your array to make a real copy of each token, but in this case, you shall have to free each token at the end.
The second solution would looks like this :
void tokenize(char **arrToStoreTokens, char *delimitedString, char *delimiter, int expectedTokenArraySize) {
//Create a clone of the original string to prevent making permanent changes to it
char *tempString = (char *)malloc(strlen(delimitedString) + 1);
strcpy(tempString, delimitedString);
if (expectedTokenArraySize >= 1) {
arrToStoreTokens[0] = strdup(strtok(tempString, delimiter)); // Here is the new part : strdup
int x;
for (x = 1; x < expectedTokenArraySize; x++ ) {
arrToStoreTokens[x] = strdup(strtok(NULL, delimiter)); // Here is the new part : strdup
}
}
//Dispose of temporary clone
free(tempString);
}
And after use of this array, you shall have to delete it, with a function like this :
void deleteTokens(char **arrToStoreTokens, int arraySize)
{
int x;
for (x = 0; x < arraySize; ++x)
{
free(arrToStoreTokens[x]);
}
}
I have problem with my array of char*-
char *original_file_name_list[500];
while(dp=readdir(dir)) != NULL) {
original_file_name = dp->d_name;
original_file_name_list[counter] = original_file_name;
printf("%s\n",original_file_name_list[0]);
printf("%d\n",counter);
counter++;
}
The problem is, that it prints all files fine. It should print only first file, right?
And if I try printf("%s\n",original_file_name_list[1]); It doesn't work , which means that it is writing only in 1st string. Any idea why?
edit: There is no syntax error due to compiler.
You're not copying the string at all - also your file_name_list array hasn't enough space for a list of filenames - just for a list of pointers. But dp->d_name is just a pointer to a char* - you can't know for how long the memory behind the pointer is valid. Because of that you have to make a copy for yourself.
#include <string.h>
#include <dirent.h>
int main(int argc, char** argv){
char original_file_name_list[50][50];
size_t counter = 0;
while(dp=readdir(dir)) != NULL) // does work fine (ordinary reading files from dir)
{
size_t len = strlen(dp->d_name);
if(len >= 50) len = 49;
strncpy(original_file_name_list[counter], dp->d_name, len);
original_file_name_list[counter][len] = '\0';
printf("%d\n",counter);
counter++;
}
printf("%s\n",original_file_name_list[1]); // <- will work if you have at least 2 files in your directory
return 0;
}
I'm not sure about purpose of counter2 (I have replaced it with counter) but I can propose the following code with strdup() call to store the file names:
char *original_file_name_list[500] = {0}; // it is better to init it here
while(dp=readdir(dir)) != NULL) {
original_file_name_list[counter] = strdup(dp->d_name); // strdup() is ok to use
// here, see the comments
printf("%s\n%d\n",original_file_name_list[counter], counter);
counter++;
}
/* some useful code */
/* don't forget to free the items of list (allocated by strdup(..) )*/
for (int i = 0; i < 500; ++i) {
free(original_file_name_list[i]);
}