Jump to content

Help with C class please

joemomma22
int main(){    FILE *read;    read=fopen("something.dat","r");    if(read!=NULL)    {        char *s=malloc(10*sizeof(char));        fscanf(read,"%s",s);        printf("%s",s);    }    return 0;}

 

Nice memory leak.

 

 

 

Don't bother allocating memory. Just use a 2D array since you know the sizes already, and it's not a huge amount of data.

 

You don't need conio.h, however you will want this http://www.cplusplus.com/reference/cstring/

main(i){for(;i<101;i++)printf("Fizz\n\0Fizzz\bBuzz\n\0%d\n"+(!(i%5)^!!(i%3)*3)*6,i);}

Link to comment
Share on other sites

Link to post
Share on other sites


char strings[51]; //is an array of 51 char elements

//if you want 51 strings, you need an array

//in wich each element points to a string

char *strings_second[51];

int i=0;

for(;i<50;i++)

strings_second=malloc(100*sizeof(char)); //strings_second[0]= a 100 char string // strings_second[0]==char[100[

Link to comment
Share on other sites

Link to post
Share on other sites

Nice memory leak.

 

 

 

Don't bother allocating memory. Just use a 2D array since you know the sizes already, and it's not a huge amount of data.

 

You don't need conio.h, however you will want this http://www.cplusplus.com/reference/cstring/

each string can hold up to 30 characters.

Link to comment
Share on other sites

Link to post
Share on other sites

what does the s pointer = malloc do/mean?

 

what i have so far: -snip-

don't use it, you don't need it

 

the char type in C holds just a single character

char c = 'x';

a string is an array of characters

char string[31] = "no more than 30 chars here";

the string must be terminated by a special character, the null terminator, which tells you where the string ends so that you stop reading the array once you reached it

if you want a string 30 chars long, you need an array that can store 30 chars + the null terminator, that's 31 chars

the C functions that you use to read and write strings will usually automatically deal with the null terminator

 

now, a string is an array of chars

you need an array of strings

so you need an array of arrays of chars, a matrix of chars

char strings[50][31];strings[0] is the first stringstrings[1] is the second string...

so, this is the kind of data structure that you want to use

use fgets to read the strings from the file, and the functions from string.h to manipulate them

Link to comment
Share on other sites

Link to post
Share on other sites

Nice memory leak.

 

 

 

Don't bother allocating memory. Just use a 2D array since you know the sizes already, and it's not a huge amount of data.

 

You don't need conio.h, however you will want this http://www.cplusplus.com/reference/cstring/

 

thanks for that link

 

don't use it, you don't need it

 

the char type in C holds just a single character

char c = 'x';

a string is an array of characters

char string[31] = "no more than 30 chars here";

the string must be terminated by a special character, the null terminator, which tells you where the string ends so that you stop reading the array once you reached it

if you want a string 30 chars long, you need an array that can store 30 chars + the null terminator, that's 31 chars

the C functions that you use to read and write strings will usually automatically deal with the null terminator

 

now, a string is an array of chars

you need an array of strings

so you need an array of arrays of chars, a matrix of chars

char strings[50][31];strings[0] is the first stringstrings[1] is the second string...

so, this is the kind of data structure that you want to use

use fgets to read the strings from the file, and the functions from string.h to manipulate them

 

yeah thank you for the information. i understand most of this, its just putting it into practice. like i mentioned previously i have my baseline down for the input, but no .length testing done because its only a 1d array. i dont understand something... and i dont even know how to put it into words. so when i use a 1d array using fgets while !feof, i read 50 strings? because it is seperated by new lines? idk how to put it im just kinda lost. also theres a part that requires removing the null bit at the end of each string, its listed on page 1 and that is throwing me off so much i have no clue how to do that.

Link to comment
Share on other sites

Link to post
Share on other sites

Your not going to learn C by getting us to answer it for you.

Link to comment
Share on other sites

Link to post
Share on other sites

Your not going to learn C by getting us to answer it for you.

ive been in CS for 4 years already, im aware of this thank you.  but sometimes i work better with example. i'm usually the one helping all the kids in the class with their stuff cause mines been done for so long, but things have gotten really busy in life lately and i have just been not understanding some of the stuff that we are doing more recently

Link to comment
Share on other sites

Link to post
Share on other sites

Oh boy. This is a fun one. Strap in boys. This'll be a long post.

 

The primary difference from java to C is that many of the things java does for you (allocate memory for dynamic strings, keep track of how large said string is, etc) do not come into play until you start using C++ instead of C. Now, to the hardware of the computer (CPU, DIMMs, etc) the strings in both java and C are the same. Why? Because Java is written in C. Shocking I know.

 

How *are* strings represented. I'm going to assume you don't know anything about how the data structures actually work in the system. Consider this pragmatic rather than insulting. The string "I'm a noob" is stored as ([] indicate one array index, 8 bits wide)

['][m][ ][a][ ][n][o][o][\0]

 

The size of that string (counting the []) is 11. 11 what? 11 chars! char is a datatype in both java and C, and it has the same size in both languages, 8 bits. In C, to store the string above in memory, you could do it one of two ways:

#include <stdio.h>#include <stdlib.h>#include <string.h>int main(){        char test[] = {'I','\'','m',' ','a',' ','n','o','o','b'};        char test2[] = "I'm a noob";        char *the_string_alloc = (char*)malloc(sizeof(char)*11);        if(the_string_alloc == NULL)        {                puts("Memory allocation failure.");                exit(2);        }        strcpy(the_string_alloc,"I'm a noob");        puts(test);        puts(test2);        puts(the_string_alloc);        printf("%ld\n",sizeof(test));        printf("%ld\n",sizeof(test2));        free(the_string_alloc);        //This may or may not work. It is most definitely a memory error, and may cause a        // segmentation fault but it might also work silently because of left over space        // in memory. It WILL cause problems eventually but not in this particular program.        strcpy(test,"I'm a noob, really!");        puts(test);        printf("%ld\n",sizeof(test));        //And when I do this print, you'll see that I did, indeed, overwrite test2 because        // I overflowed test's boundary.        puts(test2);        printf("%ld\n",sizeof(test2));}

*Note: if you execute this code, you may see something like "I'm a noob@" instead of 'I'm a noob" for the first line. This is due to out-of-order printing caused by my later-on buffer overflow. It's an example of the weird shit that happens when you overflow buffers.

 

Your professor probably doesn't want you using string.h, but that isn't the only way to get a string into an array, it's just the way I chose. Note: strncpy is preferred to strcpy as it is more secure; this is just a teaching example.

 

That last character, \0, is the representation of the 'null character'. All strings in java are null terminated. In C, strings *should* be null terminated, but don't have to be. Some functions will break (like strcpy()) if you give them a string which *isn't* null terminated, and such breakage is where many programming security vulnerabilities come from. If you have a string without an ending null character, and you aren't passing it to any functions that you yourself didn't write (IE: you never pass the string to strcpy, strtok, etc), then you can get away with not having a null character and just keeping track of the size of the string with an integer.

 

As you can see, when I statically assign the strings to char arrays, depending on how I do it, I may or may not get a null character at the end (test doesn't have a null character, test2 does). That is why test's size is 10, and test2's size is 11. C allows you to shoot yourself in the foot in this way. Also, note that I have a very serious programming issue in my code, I overflow my array (also known as a buffer). I write more than the 10 characters the buffer can hold to memory. This works silently, but when I print test2 out the second time, at the end of the program, you can see that the data it used to hold is gone, overwritten by the last bit of what was supposed to go into test.

 

Why writing to test overwrites test2 has to do with how the OS lays out memory to the application, and it is fascinating, but not important to the level of programming you are doing right this second. Ask your professor to explain it to you if you are curious.

 

But what about that char *the_string_alloc call? Right, so all three variables I create (test, test2, and the_string_alloc) are all called 'pointers'. My java class never told me that in java everything I created with the keyword 'new' was a pointer, but it was, I later learned. What is a pointer? Well, basically you can think of the literal value of 'test' being 0x8a8d93ff for example (a 32 or 64-bit (depending on OS type and what you compile the program as) integer). That integer is an address in 'heap' memory. Heap memory may be in DRAM, or swap. When you access test, the code knows to go and look at whatever value is stored in the memory address 'test' points to, hence the name 'pointer'. If you want to see this memory address:

printf("%p\n",&test);

If you run the program with that line in it several times, you'll see that the address changes. Why would that be? Well, the OS and compiler both probably support (and have enabled) address randomization. Which is an attempt to make buffer overflow attacks less effective. Also, the program isn't guaranteed a slot in memory to run, so every time it starts up, it may be assigned a new block of memory to run it, hence, the address in memory changes. The & character says "Show me the address of the pointer, instead of the value that address points to!" in this context. This is not the *only* thing the & character does.

 

In the case of test and test2, these are pointers to statically sized arrays. Size 10 and 11 respectively. the_string_alloc is a dynamically sized array. You could use the realloc() function call to change the size of the_string_alloc and make it larger or smaller, as needed. You could also simply call free() on the_string_alloc and call malloc() again.

 

Right, malloc, that function call seems scary doesn't it? Let me break it down.

char *the_string_alloc = (char*)malloc(sizeof(char)*11);

char *the_string_alloc <-- This says "Create me a char pointer called the_string_alloc"

(char*) <--"Cast the result of this function call to a char*" (by default it's a void*)

malloc() <--the function call itself, it stands for "memory allocate(or)"

 

sizeof(char) <--in C, data types do not have a guaranteed size. In a 32-bit program, the 'long' datatype might have a size of 4 (4x8 = 32 bits), but if that same code is recompiled as 64-bit code, it would suddenly have a size of 8 (8x8 = 64 bits). Therefore, non-terrible programmers do NOT request bytes of memory directly from malloc, instead, they ask for a multiple of the size of the datatype they are going to be storing.

 

sizeof(char)*11 <-- because I'm not a terrible programmer, I get the size of the char data type at run time, multiply it by 11 (because I know I need to hold 11 char-sized objects), and give *that* number as the number of bytes of memory I need malloc to allocate to me.

 

All memory given out by malloc needs to have free() called on it once it is no longer needed. Never call free() twice on the same piece of memory in an attempt to make sure it goes away! It will cause your program to crash.

===============

 

*phew* That was a lot. What did we learn? Oh, well, that was setup to cover your *first* bullet point. So strings are just char arrays? Really? All that just to explain that single concept? Oh snap, how deep of a pile of poo are you in?! :)

 

So, if a string is a single character array/pointer, how do I make one variable that can hold 50 strings?

 

Well...is there any reason you couldn't' have an array of char pointers? And then have each slot in that array of char pointers point to a string? The answer is no. In fact, this is how the full definition of main() for ANY C program passes in arguments from the command line.

int main(char **argc, int argv){}

You can visualize a char** like this:

[0]   [1]I      f'      om       ra      e       an      lo      \0ob\0

where [0] would be, for example, argv[0], and [1] would be argv[1]. Note: all of the strings in the char** do NOT need to be the same length, be sure to keep track of this if you go this route!

 

But what if I wanted to reference just the ' character in argv[0]? Well, it's no different than a two-dimensional array you used in Java, so you'd access it the same way. argv[0][1].

 

As for keeping track of the lengths of all the strings? Personally, I'd recommend an int*, that way you know the size of the string at argv[0] by going to int[0]. :)

 

How do I free a double pointer? Well, first, you free all of the hangy-down bits (free(argv[0]), free(argv[1])), then you free the double pointer itself (free(argv)). Failure to do it in this order will either cause memory leaks or program crashes.

 

Ok. That answers your first bullet point. I'll make another post for the second, since this one is quite massive all on its own. This is the teaching your professor(s) really should have given you. Perhaps they did and you simply didn't understand, perhaps they are taking your money for free. *shrug* Either way, I think any rational person can agree, I am teaching you *how* to program, not dropping the answers in your lap. You still have to understand how to put the pieces together, no? :)

 

=========

 

edit: actually, I think, if you are decent at java, the rest of this program should be easy for you to write, apart from looking up function calls, now that you understand how memory allocation and references work. Just tell me what doesn't make sense and I'll go deeper on that (unless you try to get me to write your program for you, in which case *grr* :P)

Link to comment
Share on other sites

Link to post
Share on other sites

-summary-

 

 thank you. that really does help a lot more than anyone else has. and im not asking for the answer by any means. i appreciate the effort of explaining to me like i know nothing at all, which isnt true, but is still helpful. i knew a majority of the post aside from malloc. i didnt know you could even make an array**... pointers * and adr of pointers& are still really confusing for me. not really sure why. passing things back and forth through functions is going to be a bit challenging because you cant just pass the array you have to pass the array* right? idk

Link to comment
Share on other sites

Link to post
Share on other sites

Protip: Apply the sizeof in the malloc to the object being allocated

int *i = malloc( sizeof(*i) * 10 ); 

Now, I can change i's type to anything and not touch the malloc code, or any reallocs I may have elsewhere.

 

That's also why you shouldn't cast malloc. It returns void* for a reason. C will implicitly cast it for you.

 

 

FYI, the definition of main(if you want arguments) is 

int main(int argc, char** argv) 

Any decent compiler will warn you otherwise.

 

 

and just for fun. C is flexible when it comes to addressing memory

#include <stdio.h>#include <stdlib.h>int main(void){    char str[8];    char *p = &str[1];    str[0]          = 'a';    *p              = 'b';    *(str+2)        = 'c';    p[2]            = 'd';    4[str]          = 'e';    (str+5)[0]      = 'f';    (-5)[str+11]    = 'g';    *(p+6)          = '\0';    puts(str);    return 0;}

It's all just addresses to the compiler.

main(i){for(;i<101;i++)printf("Fizz\n\0Fizzz\bBuzz\n\0%d\n"+(!(i%5)^!!(i%3)*3)*6,i);}

Link to comment
Share on other sites

Link to post
Share on other sites

Protip: Apply the sizeof in the malloc to the object being allocated

int *i = malloc( sizeof(*i) * 10 ); 

Now, I can change i's type to anything and not touch the malloc code, or any reallocs I may have elsewhere.

 

That's also why you shouldn't cast malloc. It returns void* for a reason. C will implicitly cast it for you.

 

 

FYI, the definition of main(if you want arguments) is 

int main(int argc, char** argv) 

Any decent compiler will warn you otherwise.

 

 

and just for fun. C is flexible when it comes to addressing memory

#include <stdio.h>#include <stdlib.h>int main(void){    char str[8];    char *p = &str[1];    str[0]          = 'a';    *p              = 'b';    *(str+2)        = 'c';    p[2]            = 'd';    4[str]          = 'e';    (str+5)[0]      = 'f';    (-5)[str+11]    = 'g';    *(p+6)          = '\0';    puts(str);    return 0;}

It's all just addresses to the compiler.

pparently my response didnt go through the first time i thought i answered. my main problem is figuring out when to use * and & and when not to use them at all. passing arrays through fuctions seems to use them sometimes but not always

Link to comment
Share on other sites

Link to post
Share on other sites

apparently my response didnt go through the first time i thought i answered. my main problem is figuring out when to use * and & and when not to use them at all. passing arrays through fuctions seems to use them sometimes but not always

"&" is the "address of" operator: if you apply it to a variable, it will return the memory address of that variable

"*" is the dereference operator: if you apply it to a pointer, it will return the variable/memory zone that it's been pointed

 

pointers store memory locations

arrays store a bunch of values of the same type, but if you access the name of the array without square brackets, it will return the memory address of the array

 

when you use the "*" in the variable declaration, it's not the dereference operator, but it's just syntax to say "pointer to"

int value = 42;int values[3] = {1, 2, 3};// "int*" means "pointer to int"// this variable can store the memory address of an integer variable, but it doesn't yet: it's not initialized, it's not pointing anywhere, it's "empty"int* pointer;// let's make the pointer point to the integer variablepointer = &value;// let's make the pointer point to the beginning of the array, using the array name or the first element. the two following operations are equivalentpointer = values;pointer = &values[0];

the last one is because the memory address of the array corresponds to the memory address of the first element of the array

so, when you want to pass an array as a function parameter, you pass the memory address of the array

// this one accept as a parameter a pointer to int, which can represent the initial memory address of the arrayvoid a_function(int* array){          // treat it as an array          array[0] = 5;          // or treat it as a pointer, with the dereference operator          // this one takes the memory address of the first element, and goes 1 element forward, then dereferences it to write a value in it          *(array + 1) = 12;}int main(){          int array[10];          // this does the same thing twice          a_function(array);          a_function(&array[0]);}
Link to comment
Share on other sites

Link to post
Share on other sites

 

"&" is the "address of" operator: if you apply it to a variable, it will return the memory address of that variable

"*" is the dereference operator: if you apply it to a pointer, it will return the variable/memory zone that it's been pointed

 

pointers store memory locations

arrays store a bunch of values of the same type, but if you access the name of the array without square brackets, it will return the memory address of the array

 

when you use the "*" in the variable declaration, it's not the dereference operator, but it's just syntax to say "pointer to"

int value = 42;int values[3] = {1, 2, 3};// "int*" means "pointer to int"// this variable can store the memory address of an integer variable, but it doesn't yet: it's not initialized, it's not pointing anywhere, it's "empty"int* pointer;// let's make the pointer point to the integer variablepointer = &value;// let's make the pointer point to the beginning of the array, using the array name or the first element. the two following operations are equivalentpointer = values;pointer = &values[0];

the last one is because the memory address of the array corresponds to the memory address of the first element of the array

so, when you want to pass an array as a function parameter, you pass the memory address of the array

// this one accept as a parameter a pointer to int, which can represent the initial memory address of the arrayvoid a_function(int* array){          // treat it as an array          array[0] = 5;          // or treat it as a pointer, with the dereference operator          // this one takes the memory address of the first element, and goes 1 element forward, then dereferences it to write a value in it          *(array + 1) = 12;}int main(){          int array[10];          // this does the same thing twice          a_function(array);          a_function(&array[0]);}

this helps out a lot. thank you. im still not entirely sure how im going to get this done but i at least understand it a hell of a lot more after posting. much appreciation to everyone

Link to comment
Share on other sites

Link to post
Share on other sites

 

"&" is the "address of" operator: if you apply it to a variable, it will return the memory address of that variable

"*" is the dereference operator: if you apply it to a pointer, it will return the variable/memory zone that it's been pointed

 

pointers store memory locations

arrays store a bunch of values of the same type, but if you access the name of the array without square brackets, it will return the memory address of the array

 

when you use the "*" in the variable declaration, it's not the dereference operator, but it's just syntax to say "pointer to"

int value = 42;int values[3] = {1, 2, 3};// "int*" means "pointer to int"// this variable can store the memory address of an integer variable, but it doesn't yet: it's not initialized, it's not pointing anywhere, it's "empty"int* pointer;// let's make the pointer point to the integer variablepointer = &value;// let's make the pointer point to the beginning of the array, using the array name or the first element. the two following operations are equivalentpointer = values;pointer = &values[0];

the last one is because the memory address of the array corresponds to the memory address of the first element of the array

so, when you want to pass an array as a function parameter, you pass the memory address of the array

// this one accept as a parameter a pointer to int, which can represent the initial memory address of the arrayvoid a_function(int* array){          // treat it as an array          array[0] = 5;          // or treat it as a pointer, with the dereference operator          // this one takes the memory address of the first element, and goes 1 element forward, then dereferences it to write a value in it          *(array + 1) = 12;}int main(){          int array[10];          // this does the same thing twice          a_function(array);          a_function(&array[0]);}

 

 

so.... can you help me with a section of code here... how would i go about doing the swap section of the code

void selSort(char *strings, int count){    int last = count;    for (last; last >= 1; --last)    {        loc = indexOfLargest(strings, last + 1);        swap(strings, loc, last);    }}int indexOfLargest(int *arr, int numElements){    int indLarge = 0;    int curr;    for (curr = 1; curr < numElements; ++curr)    {        if (arr[curr] > arr[indLarge])            indLarge = curr;    }    return curr;
Link to comment
Share on other sites

Link to post
Share on other sites

okay. im done. but im having problems with my print function. 

#include <stdio.h>#include <string.h>#include <conio.h>void readStrings(char *strings, int count, FILE *pFile);void printStrings(char *strings, int count);int indexOfLargest(int *arr, int numElements);void selSort(char *strings, int count);void swap(char *strings, int loc, int last);int main(){    FILE *pFile;    char strings[50][31];    int count = 0;    //Open File    pFile = fopen("Strings.dat", "r");    readStrings(strings, count, pFile);    puts("Original File:\n");    printStrings(strings, count);    selSort(strings, count);    puts("Sorted File:\n");    printStrings(strings, count);    return 0;}void readStrings(char *strings, int count, FILE *pFile){    if (pFile != NULL)    {        while(!feof(pFile), count < 50)        {            fgets(strings, 31, pFile);            count++;        }        fclose(pFile);    }}void printStrings(char *strings, int count){    int i;    for(i = 0; i < count; i++)    {        printf("%s\n", strings);    }    printf("\n");}void selSort(char *strings, int count){    int loc;    int last = count;    for (last; last >= 1; --last)    {        loc = indexOfLargest(strings, last + 1);        swap(strings, loc, last);    }}int indexOfLargest(int *arr, int numElements){    int indLarge = 0;    int curr;    for (curr = 1; curr < numElements; ++curr)    {        if (arr[curr] > arr[indLarge])            indLarge = curr;    }    return curr;}void swap(char *strings, int loc, int last){    char temp[31];    strcpy(temp, strings[loc]);    strcpy(strings[loc], strings[last]);    strcpy(strings[last], temp);}

see?

8zPPx.png

 

any suggestions?

Link to comment
Share on other sites

Link to post
Share on other sites

Look at your output window. There should be a bunch of warnings about pointers, among other things.

 

There should be at least 4 or 5 for passing an argument of incompatible pointer type.

 

char* strings is a pointer to a char. You want to pass a pointer to an array of chars. char strings[50][31] decays to (char*)[31] when passed as an argument to a function. 

 

So you'll need to make your function declarations look like this:

void foo( char strings[][31] )

When passing fixed size 2D arrays you need to inform the compiler of the second dimension, so it knows what to put on the stack. This is why 2D arrays don't decay to pointer-to-pointer(**). This is one of the few cases where pointers and arrays differ in C.

 

Your swap function should also being throwing a bunch of pointer to integer conversion warnings. You're indexing into a single dimension array, and passing whatever value is there as an address. Who knows what memory it's trying to copy? Certainly not what you want.

 

You should also have a warning about that comma in your while loop expression (line 36). && is what you're looking for. As it stands its only evaluating count < 50.

 

Line 59, remove last from the first for expression. It doesn't do anything.

 

As far as your print function, once you fix the declaration, you need to actually index into strings.

 

What are you trying to do with indexOfLargest? You are passing a char* to an int*. See strcmp. The function declaration stuff applies here too.

main(i){for(;i<101;i++)printf("Fizz\n\0Fizzz\bBuzz\n\0%d\n"+(!(i%5)^!!(i%3)*3)*6,i);}

Link to comment
Share on other sites

Link to post
Share on other sites

Look at your output window. There should be a bunch of warnings about pointers, among other things.

 

There should be at least 4 or 5 for passing an argument of incompatible pointer type.

 

char* strings is a pointer to a char. You want to pass a pointer to an array of chars. char strings[50][31] decays to (char*)[31] when passed as an argument to a function. 

 

So you'll need to make your function declarations look like this:

void foo( char strings[][31] )
When passing fixed size 2D arrays you need to inform the compiler of the second dimension, so it knows what to put on the stack. This is why 2D arrays don't decay to pointer-to-pointer(**). This is one of the few cases where pointers and arrays differ in C.

 

Your swap function should also being throwing a bunch of pointer to integer conversion warnings. You're indexing into a single dimension array, and passing whatever value is there as an address. Who knows what memory it's trying to copy? Certainly not what you want.

 

You should also have a warning about that comma in your while loop expression (line 36). && is what you're looking for. As it stands its only evaluating count < 50.

 

Line 59, remove last from the first for expression. It doesn't do anything.

 

As far as your print function, once you fix the declaration, you need to actually index into strings.

 

What are you trying to do with indexOfLargest? You are passing a char* to an int*. See strcmp. The function declaration stuff applies here too.

Oh okay I'll retry some stuff and repost it. Again I greatly appreciate the help. The knowledge is going to really help on my final.

The comma in the whole loop was cause I didn't see anything online using && so I didn't know it worked in c lol. The useless last in the for loop is probably going to remain there just cause that's code directly from the professor (see assignment posted page 1)

So now here's where I'm going awry, how do I access the strong to use strcmp or strcpy then?

Strings[0] (I =0<31) is only going to give me one character at a time. So I'm not really sure then

Link to comment
Share on other sites

Link to post
Share on other sites

I return! Oh boy. Newbie mistakes. So cute. If we were on reddit, I'd tip you some dogecoin. Anyway.

int count = 0;readStrings(strings, count, pFile);void readStrings(char *strings, int count, FILE *pFile)

Ok. Count was created on the stack, rather than the heap. This means it is directly addressed rather than accessed by a pointer. So when you pass it to readStrings() a *copy* of count's current value (in the scope of main()) is made and passed into readStrings. readStrings then has its own, independent, local copy of count. That is why when you update it within readStrings, the value of it in main() remains 0, and why putStrings fails to print anything.

 

If you want to be able to update int there are two ways:

 

1. change readStrings from a void return type to an int return type and assign the value there.

2. Change count to an int*, malloc it, and then update it that way.

 

---

fgets(strings, 31, pFile);

This call fails because you need to be reading into strings[count]. Think about it, you are telling it to always read the newest string into strings itself, not even strings[0]. You are losing the memory address of the char** array strings represents!

 

--

 

in printStrings():

printf("%s\n", strings);

Same thing as above, you need to tell it *which* string in strings to print out on each iteration. C cannot magically print an entire array for you. :P

 

--

 

--sauce--

 

any suggestions?

 

 

Let's start with those fixes and see what else is broken...mostly because I don't want to think through selection sort in my head unless I really have to. /lazy

Link to comment
Share on other sites

Link to post
Share on other sites

Oh okay I'll retry some stuff and repost it. Again I greatly appreciate the help. The knowledge is going to really help on my final.

The comma in the whole loop was cause I didn't see anything online using && so I didn't know it worked in c lol. The useless last in the for loop is probably going to remain there just cause that's code directly from the professor (see assignment posted page 1)

So now here's where I'm going awry, how do I access the strong to use strcmp or strcpy then?

Strings[0] (I =0<31) is only going to give me one character at a time. So I'm not really sure then

 

strings

 

It's equivalent to &strings[0]. That is, the address of the first element of the i'th array.

main(i){for(;i<101;i++)printf("Fizz\n\0Fizzz\bBuzz\n\0%d\n"+(!(i%5)^!!(i%3)*3)*6,i);}

Link to comment
Share on other sites

Link to post
Share on other sites

thank you. ill be sure to change some of the headers to int and return them into count. and the print string call where it printf(strings) i had it with first in a for loop but i deleted it becausae it wasnt working. was just testing diffrent circumstances. forgot to change it back to post

Link to comment
Share on other sites

Link to post
Share on other sites

I return! Oh boy. Newbie mistakes. So cute. If we were on reddit, I'd tip you some dogecoin. Anyway.

int count = 0;readStrings(strings, count, pFile);void readStrings(char *strings, int count, FILE *pFile)

Ok. Count was created on the stack, rather than the heap. This means it is directly addressed rather than accessed by a pointer. So when you pass it to readStrings() a *copy* of count's current value (in the scope of main()) is made and passed into readStrings. readStrings then has its own, independent, local copy of count. That is why when you update it within readStrings, the value of it in main() remains 0, and why putStrings fails to print anything.

 

If you want to be able to update int there are two ways:

 

1. change readStrings from a void return type to an int return type and assign the value there.

2. Change count to an int*, malloc it, and then update it that way.

 

---

fgets(strings, 31, pFile);

This call fails because you need to be reading into strings[count]. Think about it, you are telling it to always read the newest string into strings itself, not even strings[0]. You are losing the memory address of the char** array strings represents!

 

--

 

in printStrings():

printf("%s\n", strings);

Same thing as above, you need to tell it *which* string in strings to print out on each iteration. C cannot magically print an entire array for you. :P

 

--

 

 

 

Let's start with those fixes and see what else is broken...mostly because I don't want to think through selection sort in my head unless I really have to. /lazy

 

 

Look at your output window. There should be a bunch of warnings about pointers, among other things.

 

There should be at least 4 or 5 for passing an argument of incompatible pointer type.

 

char* strings is a pointer to a char. You want to pass a pointer to an array of chars. char strings[50][31] decays to (char*)[31] when passed as an argument to a function. 

 

So you'll need to make your function declarations look like this:

void foo( char strings[][31] )

When passing fixed size 2D arrays you need to inform the compiler of the second dimension, so it knows what to put on the stack. This is why 2D arrays don't decay to pointer-to-pointer(**). This is one of the few cases where pointers and arrays differ in C.

 

Your swap function should also being throwing a bunch of pointer to integer conversion warnings. You're indexing into a single dimension array, and passing whatever value is there as an address. Who knows what memory it's trying to copy? Certainly not what you want.

 

You should also have a warning about that comma in your while loop expression (line 36). && is what you're looking for. As it stands its only evaluating count < 50.

 

Line 59, remove last from the first for expression. It doesn't do anything.

 

As far as your print function, once you fix the declaration, you need to actually index into strings.

 

What are you trying to do with indexOfLargest? You are passing a char* to an int*. See strcmp. The function declaration stuff applies here too.

 

 

okay so i did a few things. readstrings is now an int, and i changed how the the strings are passed in. now, in the program when they are called, how should i pass in strings to the function that takes strings[][31]?

int readStrings(char strings[][31], int count, FILE *pFile);void printStrings(char strings[][31], int count);
Link to comment
Share on other sites

Link to post
Share on other sites

Here's a basic example

#include <stdio.h>void foo(char strs[][4], size_t cnt){    size_t i = 0;    for(; i < cnt; i++)    {        puts(strs[i]);    }}int main(void){    char strs[3][4] = {"foo", "bar", "baz"};    foo(strs, 3);    return 0;}

main(i){for(;i<101;i++)printf("Fizz\n\0Fizzz\bBuzz\n\0%d\n"+(!(i%5)^!!(i%3)*3)*6,i);}

Link to comment
Share on other sites

Link to post
Share on other sites

#include <stdio.h>#include <string.h>#include <conio.h>int readStrings(char strings[][31], int count, FILE *pFile);void printStrings(char strings[][31], int count);int indexOfLargest(char arr[][31], int numElements);void selSort(char strings[][31], int count);void swap(char strings[][31], int loc, int last);int main(){    FILE *pFile;    char strings[50][31];    int count = 0;    //Open File    pFile = fopen("Strings.dat", "r");    count = readStrings(strings, count, pFile);    puts("Original File:\n");    printStrings(strings, count);    selSort(strings, count);    puts("Sorted File:\n");    printStrings(strings, count);    //system("PAUSE");    return 0;}int readStrings(char strings[][31], int count, FILE *pFile){    if (pFile != NULL)    {        while(!feof(pFile) && count < 50)        {            fgets(strings[count], 31, pFile);            count++;        }        fclose(pFile);    }    return count;}void printStrings(char strings[][31], int count){    int i;    for(i = 0; i < count; i++)    {        printf("%s\n", strings[i]);    }    printf("\n");}void selSort(char strings[][31], int count){    int loc;    int last = count;    for (last; last >= 1; --last)    {        loc = indexOfLargest(strings, last + 1);        //swap(strings, loc, last);    }}int indexOfLargest(char arr[][31], int numElements){    int indLarge = 0;    int curr;    for (curr = 1; curr < numElements; ++curr)    {        if (strcmp(arr[curr], arr[indLarge]) > 0)            indLarge = curr;    }    return curr;}void swap(char strings[][31], int loc, int last){    char temp[31];    strcpy(temp, strings[loc]);    strcpy(strings[loc], strings[last]);    strcpy(strings[last], temp);}

well... its better, but it doesnt work. in the sorting, indexOfLargest isnt returning anywhere near a crrect value, it ends up at like 9876546576879809654657687990-09878765646576789890-0089765457687 or something. swap is commented out because calling swap with loc equalling tha tlarge number causes the program to crash.

Link to comment
Share on other sites

Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×