In my register, I want to find all the words that match user input and display them.
For example if I have words like redapple, rottenapple, apple, banana in my register.
And user inputs apple I want to be able to dispaly redapple, rottenapple, apple and their itemnumber and inventory balance. I cannot display in the right way and cannot figure it why, have tried different way and I will post my last try. Thank you!
void search(Car a[],int nr){
char ItmName[50];
int i;
while(1){
printf("Type item name (q for menu): ");
scanf("%s%*c", &ItmName);
if(strcmp(ItmName,"q")==0){
return;
}else{
for(i=0;i<nr;i++){
char *word = strstr(a[i].name,ItmName);
for(i=0;i<nr;i++)
if(word==itemN){
printf("%d\t\t%s\t\t%d\n", a[i].itemNmr, a[i].name, a[i].inventory);
}
return;
}
}
}
}
Your nested loop use the same control variable, i, and continuation condition, which ensures only one iteration of the outer loop occurs.
The contents of the loop make little sense. You repeatedly compare a pointer to the first element of the input buffer (itemN; pressumably itemName) against the pointer value returned by strstr, after it looks through the name field of only the first element of the a array for the substring provided in itemName.
Rewritten verbosely, this reads as
for (i = 0; i < nr; i++) {
for (i = 0; i < nr; i++) {
if (strstr(a[0].name, itemName) == &itemName[0]) {
printf(/* some information */);
}
}
}
which hopefully you can see makes no sense. A pointer value that points to an element of a[0].name will never be equal to the pointer value that points to the first element of itemName - as that would require their memory to overlap somehow.
In any case, this should not require any nested loops, as this can be done with a linear search of your array of structures.
First suggestion: move the user input to outside the function. Make search accept a third argument, a string to search for in each structures name. Separately (and repeatedly) take user input and then call this function.
Second suggestion: forget scanf exists entirely. Use fgets (and sscanf if you need to extract formatted data from the string).
Here's a cursory example of a linear search function:
#include <stdio.h>
#include <string.h>
typedef struct {
char name[128];
unsigned inventory;
} Car;
void search(Car *cars, size_t length, const char *query)
{
for (size_t i = 0; i < length; i++)
if (strstr(cars[i].name, query))
printf("NAME: [%s]\tQUANT: [%u]\n", cars[i].name, cars[i].inventory);
}
int main(void)
{
Car cars[] = {
{ "redapple", 10 },
{ "rottenapple", 7 },
{ "foo", 4 },
{ "bar", 15 },
{ "candyapple", 11 }
};
size_t len = sizeof cars / sizeof *cars;
while (1) {
char buf[512];
printf("Enter a search string (. = exit): ");
fflush(stdout);
if (!fgets(buf, sizeof buf, stdin))
return 1;
if ('.' == *buf)
return 0;
/* remove any trailing CRLF */
buf[strcspn(buf, "\r\n")] = '\0';
search(cars, len, buf);
}
}
Related
So I am pretty much trying to create an array that functions as following:
1)I enter a string (in a temporary array like char temp[...] for example)
2)I create a while loop that ends when the first character of temp is \x0
3)Inside the loop I use the malloc function to create space for each string
4)I print the strings
Problem is that whenever i try to run my program it crushes and the compiler isn't helping me much.
Here is the code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define LINE 80
int main(){
char **pin;
char temp[LINE];
int index = 0;
puts("Gimme Books' Titles:");
gets(temp);
while(temp[0] != '\x0'){
pin[index] = (char*)malloc(strlen(temp)+1);
strcpy(pin[index], temp);
index++;
gets(temp);
}
puts("\nBooks' List:");
for(int k = 0; k < index; k++){
puts(pin[k]);
}
}
Anyone here who can help me find out what I am doing wrong?
The link in the comments above [mostly] assumes that we know the number of elements before we allocate the array.
Thus, it's not as useful when we can only get the number of elements by reading the input file. For TTY input from stdin this won't work too well because we can't rewind the file.
A dynamic array is generally useful. So, I've created one that allows arbitrarily sized array elements. And, it can grow/expand as we add new elements.
And, for demo purposes here, I've created a "book" structure that stores Author's name and book title.
Here is the code. It is annotated:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <termios.h>
// general dynamic array control
typedef struct {
void *arr_base; // pointer to data
size_t arr_size; // bytes / element
size_t arr_count; // number of elements in use
size_t arr_capacity; // number of elements allocated
} arr_t;
// book control
typedef struct {
char *book_last; // author's last name
char *book_first; // author's first name
char *book_title; // book title
} book_t;
// arrnew -- allocate new array
arr_t *
arrnew(size_t siz)
{
arr_t *arr = calloc(1,sizeof(*arr));
// store the number of bytes in each element
arr->arr_size = siz;
return arr;
}
// arrappend -- get new element in array
// RETURNS: pointer to element
void *
arrappend(arr_t *arr)
{
size_t index;
void *ptr;
// get index of element to store into and increase the in use count
index = arr->arr_count++;
do {
// we have enough space for the new element already
if (arr->arr_count < arr->arr_capacity)
break;
// increase allocated amount
// NOTE: the increment is arbitrary
arr->arr_capacity += 10;
// grow the array
arr->arr_base = realloc(arr->arr_base,
arr->arr_capacity * arr->arr_size);
// got the larger array
if (arr->arr_base != NULL)
break;
perror("arrappend");
exit(1);
} while (0);
// point to element we can store into
ptr = arr->arr_base;
ptr += index * arr->arr_size;
return ptr;
}
// arrtrim -- trim array to number of elements actually used
void
arrtrim(arr_t *arr)
{
arr->arr_capacity = arr->arr_count;
arr->arr_base = realloc(arr->arr_base,arr->arr_capacity * arr->arr_size);
if (arr->arr_base == NULL) {
perror("arrtrim");
exit(1);
}
}
// arrfree -- free up array storage
void
arrfree(arr_t *arr)
{
free(arr->arr_base);
free(arr);
}
int
main(void)
{
char buf[300];
char *cp;
book_t *book;
// echo line if input is _not_ a tty [mostly for demo]
struct termios tio;
int echo = tcgetattr(fileno(stdin),&tio) < 0;
// get new array
arr_t *arr = arrnew(sizeof(book_t));
printf("Gimme Books's Titles:\n");
while (1) {
// get next line -- stop on EOF
char *cp = fgets(buf,sizeof(buf),stdin);
if (cp == NULL)
break;
// echo line if input is _not_ a tty
if (echo)
fputs(buf,stdout);
// strip newline
buf[strcspn(buf,"\n")] = 0;
// stop on blank line
if (buf[0] == 0)
break;
// get new book struct
book = arrappend(arr);
// get author's last name
char *tok = strtok(buf," \t");
book->book_last = strdup(tok);
// get author's first name
tok = strtok(NULL," \t");
book->book_first = strdup(tok);
// get the book title
tok += strlen(tok);
++tok;
for (; *tok != 0; ++tok) {
if (*tok != ' ')
break;
}
book->book_title = strdup(tok);
}
arrtrim(arr);
// show all the books
book = arr->arr_base;
for (size_t idx = 0; idx < arr->arr_count; ++idx, ++book)
printf("Last: %s First: %s Title: %s\n",
book->book_last,book->book_first,book->book_title);
// release storage for each book
book = arr->arr_base;
for (size_t idx = 0; idx < arr->arr_count; ++idx, ++book) {
free(book->book_last);
free(book->book_first);
free(book->book_title);
}
// release array storage
arrfree(arr);
return 0;
}
Here is the program input:
Lambstewer Abel A Tale of Two Cities
Smith John A baker's tale
Jones Fred Never On Sunday
Here is the program output:
Gimme Books's Titles:
Lambstewer Abel A Tale of Two Cities
Smith John A baker's tale
Jones Fred Never On Sunday
Last: Lambstewer First: Abel Title: A Tale of Two Cities
Last: Smith First: John Title: A baker's tale
Last: Jones First: Fred Title: Never On Sunday
I am trying to input to this array of strings with myFgets, but it is telling me that I have an access violation error when I do so.
What am I doing wrong here?
#include <stdio.h>
#include <string.h>
void myFgets(char str[], int size)
{
fgets(str, size, stdin);
str[strcspn(str, "\n")] = 0;
}
void enterFriends(char** friendsArr)
{
int i = 0;
for (i = 0; i < 3; i++)
{
printf("enter friend %d: ", i + 1);
myFgets(friendsArr[i], 10);
}
}
int main(void)
{
char friendsArr[3][10] = { ' ' };
int i = 0;
enterFriends(friendsArr);
for (i = 0; i < 3; i++)
{
puts(friendsArr[i]);
}
return 0;
}
Continuing from the comment, your access violation is because friendsArr is type char (*)[10] which is not the same as char **. (the first is a pointer-to-array, the second is a pointer-to-pointer) Type controls pointer arithmetic. (e.g. the offset between p and p + 1). Your 3 x 10 2D array is an array of 1D arrays.
Since an array is converted to a pointer to its first element1, friendsArr is converted to a pointer to the first array (e.g. a 10-character array), which is why the formal type on access is char (*)[10] (a pointer to array of 10-characters). So when you access the next pointer, the offset is to the beginning of the next 1D array (offset of 10-characters/bytes).
When you attempt to pass the array as char **, the offset is no longer 10-character, but instead sizeof (a_pointer). So the offset will be either 4-bytes on x86 of 8-bytes on x86_64. So what happens is you read the first string into the first 1D array, advance 8-bytes (or 4-bytes) and then attempt to read the next string into the same 1D array beginning at the 8th (or 4th) element of the array corrupting the input.
Which brings up the next critical point you are missing. You must ALWAYS check the return of every input function used to determine whether the input succeeded or failed. It is 100% valid for the user to press ctrl + d (or ctrl + z on windows) to generate a manual EOF to cancel input. By checking the return of fgets() you can properly handle that case. Further, any function you write that takes input must have a meaningful return type that can communicate success or failure of the input back to the caller.
In myFgets(), returning a pointer to the string on success (or NULL on failure) would tell enterFriends() if that input succeeded or failed. Since enterFriends() also relies on that return, it too needs a meaningful return type to communicate how many inputs succeeded. Which brings up an additional point, you cannot simply loop a fixed number of times in enterFriends(), but instead need to condition your loop on a successful read of the number of friends less than your maximum. If the user cancels input, you still want to be able to return the number that were successfully entered.
(note: you can adjust the test to require that all inputs are made, re-prompting for the canceled input -- up to you)
Don't use MagicNumbers in your code (e.g. 3, 10), instead:
#define NFRIENDS 3 /* if you need a constant, #define one (or more) */
#define MAXC 1024
(note: Rule: Don't Skimp on Buffer Size, 10 is way to short for user input. Unless you are on an embedded system with limited physical memory, then a 256-byte to 2048-byte buffer is fine. For example, GCC defines BUFSIZ as 8192, VS defines it as 512)
This also plays into whether your code is mixing VLAs (Variable Length Arrays) as parameters with your declarations of Plain-Old arrays in main(). While the difference is largely semantics in this case, be aware that compiler support for VLAs is optional beginning with C11.
So putting that altogether, you can rewrite your code slightly, tweaking the function parameters and returns to avoid VLAs and provided minimal necessary returns to communicate the success or failure of input and how many friends were read as follows:
#include <stdio.h>
#include <string.h>
#define NFRIENDS 3 /* if you need a constant, #define one (or more) */
#define MAXC 1024
/* every function that takes input must provide a meaningful return
* that can indicate success or failure to the caller.
* returns pointer to string on success, NULL otherwise.
*/
char *myFgets (char *str, int size)
{
if (!fgets (str, size, stdin)) { /* validate EVERY input */
puts ("(user canceled input)");
return NULL;
}
str[strcspn(str, "\n")] = 0; /* good job using strcspn() */
return str;
}
/* do not use MagicNumbers, pass a parameter for number of friends */
int enterFriends (char (*friendsArr)[MAXC], size_t size, int nfriends)
{
int i = 0;
while (i < nfriends) { /* can't use a fixed number */
printf ("enter friend %d: ", i + 1);
if (!myFgets (friendsArr[i], size)) /* if user cancels, break loop */
break;
i += 1; /* only increment after good read */
}
return i; /* return number of friends read */
}
int main(void)
{
char friendsArr[NFRIENDS][MAXC] = {""}; /* initialize all elements zero */
int i = 0,
friends = 0;
friends = enterFriends (friendsArr, MAXC, NFRIENDS);
for (i = 0; i < friends; i++) {
puts (friendsArr[i]);
}
}
Example Use/Output
$ ./bin/friendsarray
enter friend 1: Mickey Mouse
enter friend 2: Minnie Mouse
enter friend 3: Goofy (the dog)
Mickey Mouse
Minnie Mouse
Goofy (the dog)
or intentionally canceling the last input:
$ ./bin/friendsarray
enter friend 1: Mickey Mouse
enter friend 2: Minnie Mouse
enter friend 3: (user canceled input)
Mickey Mouse
Minnie Mouse
which properly preserves the two good inputs before the cancellation occurred.
Look things over and let me know if you have further questions.
Footnotes:
1. C11 Standard - 6.3.2.1 Other Operands - Lvalues, arrays, and function designators(p3)
The way that you are passing a 2D array in a function is not correct.
Simply pass in the array size along with it.
Eg:
void enterFriends(int m,int n,char friendsArr[m][n]){
}
// while calling that function
enterFriends(3,10,friendsArr);
Reference link: https://www.techiedelight.com/pass-2d-array-function-parameter/
Full Code:
#include <stdio.h>
#include <string.h>
void myFgets(char str[], int size)
{
fgets(str, size, stdin);
str[strcspn(str, "\n")] = 0;
}
void enterFriends(int m,int n,char friendsArr[m][n])
{
int i = 0;
for (i = 0; i < 3; i++)
{
printf("enter friend %d: ", i + 1);
myFgets(friendsArr[i], 10);
}
}
int main(void)
{
char friendsArr[3][10] = { ' ' };
int i = 0;
enterFriends(3,10,friendsArr);
for (i = 0; i < 3; i++)
{
puts(friendsArr[i]);
}
return 0;
}
void myFgets(char str[], int size)
{
fgets(str, size, stdin);
str[strcspn(str, "\n")] = 0;
}
void enterFriends(size_t size, char (*friendsArr)[size])
{
int i = 0;
for (i = 0; i < 3; i++)
{
printf("enter friend %d: ", i + 1);
myFgets(friendsArr[i], 10);
}
}
int main(void)
{
char friendsArr[3][10] = { ' ' };
int i = 0;
enterFriends(10, friendsArr);
for (i = 0; i < 3; i++)
{
puts(friendsArr[i]);
}
}
I am trying to improve my C skills so I apologize if my question is long. I am having a hard time understanding as to why my struct pointer holds the wrong value in my program, I tried to debug it but I am still relatively new to C and was hoping one of you could tell me what I'm doing wrong here and how I could improve my code and what to focus on.
I am making a program that stores user data on this struct and then prints it out.
typedef struct table {
char *firstName;
char *lastName;
int id;
}USER;
This function below stores the first name
void firstName(int *counter, int *check, USER *pt) {
for (int i = *counter; i < *check; i++) {
pt[i].firstName = calloc (MAX_LENGTH, sizeof(pt));
printf("Enter First Name: ");
getchar();
fgets(pt[i].firstName, MAX_LENGTH, stdin);
}
}
This is just my bool function returning true or false
bool isTrue(char *decision) {
if(*decision == 'Y') {
return true;
}
else {
return false;
}
}
And this is my main
int main(int argc, char **argv) {
USER *pt = calloc(1, sizeof(pt));
int counter = 0, check = 0;
char decision = '\0';
while (1) {
printf("Would you like to enter a user?(Y/N):");
fgets(&decision, 2, stdin);
strtok(&decision, "\n"); //remove the newline char
if (!isTrue(&decision)) {
break;
}
if (counter != 0) {
pt = realloc(pt, sizeof(pt) * 10); //the 10 is temporary
}
check = counter + 1; // make sure loop only runs once.
firstName(&counter, &check, pt);
++counter; // increment counter;
}
printStruct(pt, &counter);
return 0;
}
When I run it out sometimes it works fine and returns everything and sometimes it skips a value. This is what I get. It skips the value at pointer index 1 and prints garbage instead.
Would you like to enter a user?(Y/N):N
First name at array 0 is Ermir
First name at array 1 is P#1First name at array 2 is Kevin
First name at array 3 is Blaus
First name at array 4 is Adam
Also I was wondering why is it when I realloc here If i do I get a realloc error when I enter the second name.
if (counter != 0) {
pt = realloc(pt, sizeof(pt) * 10); //realloc(pt, sizeof(pt) * counter + 1) wont work
}
char decision = '\0';
...
fgets(&decision, 2, stdin);
You are only allocating 1 char but are at least reading 2 chars into it. Fix by allocating a sufficiently sized array for decision.
Unrelated but in firstName() pt[i].firstName = calloc (MAX_LENGTH, sizeof(pt)); should be pt[i].firstName = calloc (MAX_LENGTH, 1);
I prefer to create a Dictionary object and add 3 words to it.
My program has no compilation error but gets a run time error in the second for loop, is the problem in addNewWord function? Do I need pass a pointer to the DictionaryWord object ?
Please help me.
#include<stdio.h>
#include<conio.h>
#include<stdlib.h>
#include<string.h>
typedef struct{
char* name;
char* mean;
} Words;
typedef struct{
Words* word;
int size;
} Dictionary;
Dictionary createNewDictionary();
Words createNewWord();
void addNewWord(Words newword, Dictionary dic);
Dictionary createNewDictionary(){
Dictionary dic;
dic.size = 0;
dic.word = (Words*)malloc(dic.size*sizeof(Words));
return dic;
}
Words createNewWord(){
Words newword;
newword.name = (char*)malloc(30*sizeof(char));
newword.mean = (char*)malloc(30*sizeof(char));
printf("============================\n");
printf("Enter word: ");
scanf("%[^\n]", newword.name);
fflush(stdin);
printf("\nEnter meaning: ");
scanf("%[^\n]", newword.mean);
return newword;
}
void addNewWord(Words newword, Dictionary dic){
dic.size++;
dic.word = (Words*)realloc(dic.word,dic.size*sizeof(Words));
strcpy(dic.word[dic.size-1].name, newword.name);
strcpy(dic.word[dic.size-1].mean, newword.mean);
}
int main(){
Dictionary d = createNewDictionary();
for (int i=0;i<3;i++){
addNewWord(createNewWord(), d);
}
return 0;
}
There are lots of problem with your code:
Given the longest word in English is around 30 characters, this size allocation is realistic for the word, but not for the defintion:
newword.name = (char*)malloc(30*sizeof(char));
newword.mean = (char*)malloc(30*sizeof(char));
This makes little obvious sense:
dic.size = 0;
dic.word = (Words*)malloc(dic.size*sizeof(Words));
you called malloc() on zero! You're only spared by your later realloc(). Even if intentional, it really deserves a comment.
This doesn't really work as fflush() is for output streams:
fflush(stdin);
see: How to clear input buffer in C? And whatever fix you use has to apply to both scanf() calls, not just one!
Per #Jarvis, this doesn't work:
dic.word = (Words*)realloc(dic.word,dic.size*sizeof(Words));
strcpy(dic.word[dic.size-1].name, newword.name);
strcpy(dic.word[dic.size-1].mean, newword.mean);
as you didn't allocate any space for name and mean in dic so you're copying into random memory.
Per #Jarvis, doesn't work:
void addNewWord(Words newword, Dictionary dic){
dic.size++;
dic.word = (Words*)realloc(dic.word,dic.size*sizeof(Words));
You're passing dic by value so inside addnewWord() you've a copy of dic so the original dic's size will be the same as it was before the call!
Memory leak:
addNewWord(createNewWord(), d);
you dropped your handle onto what createNewWord() returned so you can never free the memory it malloc()'d
You malloc() memory but provide no means to eventually free it.
Passing and returning structs by value is a disaster in a situation like this, as the data keeps getting copied. At the least it's inefficient, at worst its buggy like the size issue above. Rather than risk it, pretend they can only be passed and returned by pointer and you'll be playing it safe and get a better result.
Below is a rework of your code (in C) with fixes, style tweaks and an attempt at a consistent terminology. It also provides some minimal test code and the ability to free your data:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_WORD_LENGTH 30
#define MAX_DEFINITION_LENGTH 1024
typedef struct entry {
char *word;
char *definition;
} Entry;
typedef struct dictionary {
Entry *entries;
int num_entries, max_entries;
} Dictionary;
Dictionary *createNewDictionary() {
Dictionary *dictionary = malloc(sizeof(*dictionary));
dictionary->num_entries = 0;
dictionary->max_entries = 1;
dictionary->entries = calloc(dictionary->max_entries, sizeof(*dictionary->entries));
return dictionary;
}
void freeEntry(Entry *entry) {
free(entry->word);
free(entry->definition);
free(entry);
}
void freeDictionary(Dictionary *dictionary) {
for (--dictionary->num_entries; dictionary->num_entries >= 0; --dictionary->num_entries) {
// we can't call freeWord() here -- why.
free(dictionary->entries[dictionary->num_entries].word);
free(dictionary->entries[dictionary->num_entries].definition);
}
free(dictionary->entries);
free(dictionary);
}
void purgeInput() {
int c;
while ((c = getchar()) != '\n' && c != EOF) { }
}
Entry *requestNewEntry() {
Entry *entry = malloc(sizeof(*entry));
entry->word = malloc(MAX_WORD_LENGTH);
entry->definition = malloc(MAX_DEFINITION_LENGTH);
printf("============================\n");
printf("Enter word: ");
scanf("%[^\n]", entry->word);
purgeInput();
printf("\nEnter definition: ");
scanf("%[^\n]", entry->definition);
purgeInput();
return entry;
}
void addNewEntry(Entry *entry, Dictionary *dictionary) {
if (dictionary->num_entries == dictionary->max_entries) {
dictionary->max_entries *= 2;
dictionary->entries = realloc(dictionary->entries, dictionary->max_entries * sizeof(*dictionary->entries));
// check if realloc returns NULL and if so, handle the error.
}
dictionary->entries[dictionary->num_entries].word = strdup(entry->word);
dictionary->entries[dictionary->num_entries].definition = strdup(entry->definition);
dictionary->num_entries++;
}
int main() {
Dictionary *d = createNewDictionary();
for (int i = 0; i < 3; i++) {
Entry *e = requestNewEntry();
addNewEntry(e, d);
freeEntry(e);
}
printf("\nRead: ");
for (int i = 0; i < d->num_entries; i++) {
printf("%s (%lu chars) ", d->entries[i].word, strlen(d->entries[i].definition));
}
printf("\n");
freeDictionary(d);
return 0;
}
CREATING A PUN DICTIONARY
> ./a.out
============================
Enter word: silkworm
Enter definition: Two silkworms had a race but ended up in a tie.
============================
Enter word: horse
Enter definition: A horse is a stable animal.
============================
Enter word: termite
Enter definition: A termite walks into a pub and asks, "Is the bar tender here?"
Read: silkworm (47 chars) horse (27 chars) termite (62 chars)
>
I see what's wrong with your code. First of all, you need to pass your Dictionary object by pointer to the function, addNewWord, and in the function addNewWord, you again need to allocate memory to each of the char* fields, name and mean, of the dic object. Here is the corrected code :
void addNewWord(Words newword, Dictionary *dic){
dic->size++;
dic->word = (Words*)realloc(dic->word, dic->size*sizeof(Words));
dic->word[dic->size-1].name = (char*)malloc(30*sizeof(char)); //added
dic->word[dic->size-1].mean = (char*)malloc(30*sizeof(char)); //added
strcpy(dic->word[dic->size-1].name, newword.name);
strcpy(dic->word[dic->size-1].mean, newword.mean);
}
Pass the dictionary's address as :
addNewWord(createNewWord(), &d);
and change the definition as well as prototype of the function as well :
void addNewWord(Words newword, Dictionary *dic)
Find the complete code here : http://pastebin.com/ZN69hevj
What I want to do is: The user inputs a string with commas; for example: 123456,44,55,,66
and I want to separate it and store in a new array without the commas; for example:
m[0][]={123456}, m[1][]={44}, m[2][]={55}, m[3][]={}, m[4][]={66}
123456 is the student ID number, 44 is the mark for 1st module, 55 is the mark for 2nd module, NULL means that the student didn't take that 3rd module, and 66 is the mark for 4th module.
How can I exactly do that? What I know is that by detecting double commas, it means the student didn't take that 3rd module.
Here is what I have written so far:
#include <stdio.h>
#include <string.h>
#include <ctype.h>
void copystring(char m[],char temp[]);
main()
{
char temp[10000];
char m[10000][10000];
gets(temp);
copystring(m,temp);
printf("%s\n",m);
return 0;
}
void copystring(char m[],char temp[])
{
int i;
int j;
for (j=0;j<(strlen(temp));j++)
{
for (i=0;i<(strlen(temp));i++)
{
if (temp[i]!=*(",")&&temp[i]!=*(" "))
{
m[j][i]=temp[i];
}
}
}
}
I have edited my code so that you can understand how to declare a function prototype containing 2D array as parameter. Also use fgets() instead of gets(). The function returns the number of marks read , i.e. an integer. I think this might help. Run the code and look on the man pages or google to understand fgets() better.
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#define SIZE 1000
int stringcopy(char m[][SIZE],char temp[]);
main()
{
char temp[SIZE],m[100][SIZE];
fgets(temp,SIZE,stdin);
int num=stringcopy(m,temp);
int i;
for(i=0;i<num;++i)
printf("%s\n",m[i]);
return 0;
}
int stringcopy(char m[][SIZE],char temp[]) {
int len=strlen(temp);
int i,j=0,k=0;
for(i=0;i<len;++i) {
if(temp[i]!=',')
m[j][k++]=temp[i];
else {
m[j][k]='\0';
++j;
k=0;
}
}
m[j][k-1]='\0';
return j+1;
}
You have to solve your problem in different steps,
The first step is to check how many tokens you have in your input string to be able to allocate enough space to store an array of tokens.
Then you should extract the tokens of the input strings in your tokens string array. To extract the tokens from your input string, you can use the strtok function from <string.h>.
Finally you can use your tokens however you want, like converting them to long in your case.
EDIT: given the requirements, here is a small implementation of what you could do. I don't check the returns of the malloc, you maybe should do it.
int main(int argc, char** argv) {
int i;
char* input_string = /* your input string for somewhere */;
char** tokens;
int tokens_count = 0;
char* input_ptr = input_string;
char* tmp_token;
size_t tmp_token_length;
// count the occurences of your separtor to have the number of elements
for(; input_ptr[tokens_count]; input_ptr[tokens_count] == ',' ? tokens_count++ : input_ptr++);
if(tokens_count == 0) {
// no tokens found, what do you want to do here ?
}
else {
// build our tokens array
tokens = malloc(sizeof(*tokens) * tokens_count);
i = 0;
tmp_token = strtok(input_string, ',');
while(tmp_token != NULL) {
tmp_token_length = strlen(tmp_token);
if(tmp_token_length != 0) {
tokens[i] = malloc(tmp_token_length);
strcpy(tokens[i], tmp_token);
}
else {
tokens[i] = NULL;
}
i++;
tmp_token = strtok(input_string, ',');
}
// populate your array of arrays of integers
long** m = malloc(sizeof(long*) * tokens_count);
for(i=0; i<tokens_count; i++) {
char* tmp_token = tokens[i];
if(tmp_token == NULL) {
m[i] = NULL;
}
else {
m[i] = malloc(sizeof(long));
m[i][0] = strtol(tmp_token, NULL, 10);
}
}
}
}
However, you should probably change your data structure by using structures instead of a massive array.
Try to use scanf for getting input, your copystring function seems fine; but if there is a problem then debug it to see what the problem is.
for (j=0;j<(strlen(temp));j++)
{
for (i=0;i<(strlen(temp));i++)
{
if (temp[i]!=(',')&&temp[i]!=(' '))
{
m[j][i]=temp[i];
}
else{
m[j][i]='\0';break;// must end a string with null character.
}
}
}
and for priting use
printf("%s",m[0]);// make a loop for it
You can read entire string using fgets, or scanf and then use strtok(string, ",") to get substrings between commas.
To detect if student has missed some entry, there are many ways, few of them are:
1) Check no. of sub-strings you get before strtok returns NULL.
2) You can search for substring ,, using strstr in the input string.