Searching for string in char array of strings in C - c

char names [MAX_CLASS_SIZE][MAX_NAME_SIZE+1]={"Julias Hoffman","Dianne Conner","Mitchell Cooper","Johnnie Greene","Johanna Mason","Kevin Adkins","Brandi Spencer","Marian Tyler","Chester Cross","Martin Lawrence","Jane Smith","Sara Jones"};
char specificName[]="";
int search(char names[][MAX_NAME_SIZE+1],char specificName[])
for(i=0;i<MAX_CLASS_SIZE;i++){
if (strcmp(names[i],specificName)==0)
{
printf("Found %s",names[i]);
return i;
}
}
This function receives an array of strings, called name and an array of characters that represents a specific name. This function searches through the array name for the specific name and returns the index of the specific name if it is found, -1 if it is not found.
In main() I ask the user for a name and store it in the specificName char array using scanf("%s",specificName);. Then in the search() function I am attempting to search the array of names for the user given name and return a certain value based on if the name is found. I have included the necessary libraries. I am trying to do this using strcmp, but search() doesn't find the matching name.

You could try the following approach:
#include <stdio.h>
#include <stdlib.h>
#include<string.h>
int search(char **names,char *specificName, size_t length){
size_t i,found=0;
for(i=0;i<length;i++){
if (strcmp(*(names + i),specificName)==0){
found = 1;
}
}
return found == 1 ? 0 : 1;
}
int main(void) {
size_t length;
char specificName[100];
char *names[12]={"Julias Hoffman","Dianne Conner","Mitchell Cooper","Johnnie Greene",
"Johanna Mason","Kevin Adkins","Brandi Spencer","Marian Tyler",
"Chester Cross","Martin Lawrence","Jane Smith","Sara Jones"};
length = sizeof names / sizeof *(names + 0);
printf("Type a name to be searched:> ");
if( fgets (specificName, 100, stdin) == NULL){
printf("Error!\n");
}
specificName[strcspn(specificName, "\n")] = 0;
if((search(names,specificName,length)) == 0){
printf("Found %s",specificName);
}else{
printf("There was no Record Found.\n");
}
return 0;
}
Output:
Type a name to be searched:> Sara Jones
Found Sara Jones

Took a quick look and it seems to work fine. Your i needs to be declared as an int but otherwise, the following works:
#include <stdio.h>
#include <stdlib.h>
#define MAX_CLASS_SIZE 100
#define MAX_NAME_SIZE 100
int strcmp(const char *, const char *);
int main(int argc, const char * argv[]) {
char names [MAX_CLASS_SIZE][MAX_NAME_SIZE+1]={"Julias Hoffman","Dianne Conner","Mitchell Cooper","Johnnie Greene","Johanna Mason","Kevin Adkins","Brandi Spencer","Marian Tyler","Chester Cross","Martin Lawrence","Jane Smith","Sara Jones"};
char specificName[]="Brandi Spencer";
int search(char names[][MAX_NAME_SIZE+1],char specificName[]);
for(int i=0;i<MAX_CLASS_SIZE;i++){
if (strcmp(names[i],specificName)==0){
printf("Found %s",names[i]);
return i;
}
}
return 0;
}
Output
Found Brandi Spencer
My guess would be is that you are not passing the user input correctly. Check specificName[] prior to strcmp().

Related

Issue printing strings from struct in c

I am trying to write a program that takes first names and last names from stdin separated by newline and stores them in char arrays inside of a struct array. Everything seems to be working fine until I want to print them in a certain way. I need the names to be formatted like this on the output:
<lastName>, <firstName> That is why I added a function to remove the trailing newline from the end of each line when parsing the values. It however does not return anything when doing this:
printf("%s, %s",people[0].lastName, people[0].firstName);
However when printing the values on seperate lines like
printf("%s\n",people[0].lastName);
printf("%s\n",people[0].firstName);
or using puts
puts(people[0].lastName);
it works just fine.
When I comment out the removeNewline() function it seems to get rid of the problem. But with the newline at the end I cannot format the output the way I desribed.
Here is my full code:
#include <stdio.h>
#include <string.h>
#define MAX_STRING_LENGTH 100
#define MAX_PEOPLE 42
struct Person{
char firstName [MAX_STRING_LENGTH];
char lastName[MAX_STRING_LENGTH];
};
void removeNewline(char * string){
for(int i = 0; string[i] != '\0'; i++){
if(string[i] == '\n'){
string[i] = '\0';
}
}
}
int parseData(struct Person * people){
int peopleCounter;
for(peopleCounter = 0; peopleCounter < MAX_PEOPLE; peopleCounter++){
char firstName[MAX_STRING_LENGTH];
char lastName[MAX_STRING_LENGTH];
if(fgets(firstName,MAX_STRING_LENGTH,stdin) == NULL){
break;
}
fgets(lastName,MAX_STRING_LENGTH,stdin);
removeNewline(firstName);
removeNewline(lastName);
strcpy(people[peopleCounter].firstName,firstName);
strcpy(people[peopleCounter].lastName,lastName);
}
return peopleCounter;
}
int main(int argc, char *argv[]){
struct Person people [MAX_PEOPLE];
parseData(people);
//PROBLEM
printf("%s, %s",people[0].firstName, people[0].lastName);
for(int i = 0; i < 2; i++){
printperson(people, i);
}
}
I am giving the values from a text file through redirection like so:
./main <people.txt
people.txt example:
George
Washington
Thomas
Jefferson
desired output:
Washington, George
Jefferson, Thomas
I am not able to reproduce the issue. Here are the minor changes:
removeNewline(): return after we process the first newline. Streamlined it a bit.
parseData(): store directly in struct instead of temporary variables. Renamed peopleCounter to i as it was it unnecessary long. Check return value of 2nd fgets(), too.
main(): Removed call to printperson() and looped over the returned values with the two arguments variables switched in the printf() statement for the expected order.
#include <stdio.h>
#include <string.h>
#define MAX_STRING_LENGTH 100
#define MAX_PEOPLE 42
struct Person{
char firstName[MAX_STRING_LENGTH];
char lastName[MAX_STRING_LENGTH];
};
void removeNewline(char *s) {
for(;;) {
*s *= (*s != '\n');
if(!*s++) return;
}
}
int parseData(struct Person *people){
int i = 0;
for(; i < MAX_PEOPLE; i++){
if(!fgets((people + i)->firstName,MAX_STRING_LENGTH,stdin))
break;
removeNewline((people + i)->firstName);
if(!fgets((people + i)->lastName,MAX_STRING_LENGTH,stdin))
break;
removeNewline((people + i)->lastName);
}
return i;
}
int main(int argc, char *argv[]) {
struct Person people[MAX_PEOPLE];
int n = parseData(people);
for(int i = 0; i < n; i++) {
printf("%s, %s\n", people[i].lastName, people[i].firstName);
}
}
and the output is:
Washington, George
Jefferson, Thomas

I am doing an assignment that asks me to make a function that creates an acronym from a string, then return the acronym

The prompt that I'm given is: An acronym is a word formed from the initial letters of words in a set phrase. Write a program whose input is a phrase and whose output is an acronym of the input. If a word begins with a lower case letter, don't include that letter in the acronym. Assume there will be at least one upper case letter in the input.
Also, I am given the following function to use: void CreateAcronym(char userPhrase[], char userAcronym[]).
My problem with the code is that only the first letter is being saved to the userAcronym variable.
For example, when the string is Institute of Electrical and Electronics Engineers. The output I'm getting is just I. What do I need to change to get the remaining letters?
Thank you for the help.
My code so far is:
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#define MAX 60
void CreateAcronym(char userPhrase[], char userAcronym[]){
int i;
int j=0;
for(i = 0; i < strlen(userPhrase); ++i){
if(isupper(userPhrase[i])){
userAcronym[j]=userPhrase[i];
}
j++;
}
printf("%s", userAcronym);
}
int main(void) {
char phrase[MAX];
char acronym[10];
fgets(phrase, MAX, stdin);
CreateAcronym(phrase, acronym);
return 0;
}
For starters the function CreateAcronym should be declared at least like
void CreateAcronym( const char userPhrase[], char userAcronym[]);
because the passed string that contains a phrase is not being changed within the function.
But it will be even better to declare the function like
char * CreateAcronym( const char userPhrase[], char userAcronym[]);
The function should not output anything. It is the caller of the function that decides whether to output the acronym formed within the function.
The function invokes undefined behavior because the array acronym does not get a string.
Moreover there is another bug in the for loop
for(i = 0; i < strlen(userPhrase); ++i){
if(isupper(userPhrase[i])){
userAcronym[j]=userPhrase[i];
}
j++;
}
where the variable j is incremented in each iteration of the loop.
And calling the function strlen in the condition of the loop is inefficient.
Also the function does not copy only initial upper case letters of words to the destination array. It tries to copy any upper case letter. So the for loop in any case does not make a sense.
The function can be defined the following way as it is shown in the demonstrative program below.
#include <stdio.h>
#include <ctype.h>
char * CreateAcronym( const char userPhrase[], char userAcronym[] )
{
char *p = userAcronym;
while ( *userPhrase )
{
while ( isspace( ( unsigned char )*userPhrase ) ) ++userPhrase;
if ( isupper( ( unsigned char )*userPhrase ) ) *p++ = *userPhrase;
while ( *userPhrase && !isspace( ( unsigned char )*userPhrase ) ) ++userPhrase;
}
*p = '\0';
return userAcronym;
}
int main(void)
{
const char *phrase = "Institute of Electrical and Electronics Engineers";
char acronym[10];
puts( CreateAcronym( phrase, acronym ) );
return 0;
}
The program output is
IEEE
Try it. First, you used j++ not in "if". And second, you didnt put '\0' in your userAcronym string. '\0' means that your string end here and all string will be printed before this symbol.
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#define MAX 60
void CreateAcronym(char userPhrase[], char userAcronym[]){
int i;
int j = 0;
for(i = 0; i < strlen(userPhrase); i++){
if(isupper(userPhrase[i])){
userAcronym[j] = userPhrase[i];
j++;
}
}
userAcronym[j] = '\0';
printf("%s", userAcronym);
}
int main(){
char phrase[MAX];
char acronym[10];
fgets(phrase, MAX, stdin);
CreateAcronym(phrase, acronym);
return 0;
}

Undefined reference to `startswith'

I am writing some C in which the program is going to convert the first command line argument into a int and check to see if it is an int. If it isnt a integer value it will then attempt to check to see whether the string begins with a '.' character or not. For some reason I am getting an undefined reference. How is this an undefined reference when it seems to be defined?
Here is the following code:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <ctype.h>
#include <string.h>
int startswith(char,char);
int main(int argc, char * argv[]) {
int forst;
srand(time(NULL));
int speed_delay = rand() % 20;
printf("The speed delay is:%i\n", speed_delay);
int first = atoi(argv[1]);
printf("First:%i\n", first);
if (first == 0) {
//this means text was inserted instead of a number
if (startswith(first, '.')) {
printf("string starts with a period !");
}
} else {
}
int startswith(const char * one,
const char * two) {
if (strncmp(one, two, strlen(two)) == 0) {
return 1;
}
return 0;
}
}
Your declaration and definition of startswith are incompatible.
The declaration has two parameters of type char, but the function actually has two parameters of type const char *.
You also defined startswith inside of main. Functions cannot be nested.
Because no function exists that matches the declaration, you have an undefined reference.
Fix your declaration to match the definition.
int startswith( const char *, const char *);
You're also not calling this function correctly. You pass in an int and a char. It should be called like this:
if(startswith(argv[1],"."))
Try replacing int startswith(char,char); with below
static inline const char *startwith(const char *s, const char *prefix)
{
size_t sz = prefix ? strlen(prefix) : 0;
if(s && sz && strncmp(s, prefix, sz) == 0){
return s+sz;
}
return NULL;
}

returning 2d array in C…

I'm a total noob in C. I can't make the connect between this function and main. I'm trying to print out a 2d array and I keep getting segmentation fault. Any help would be greatly appreciated.
EDIT: When I changed the last line 'printf("%d:[%s]\n",i,*(p+i))' from %s to %c, I get the first word in the file i'm reading from. So turns out that something is in fact being returned from my function. Now just need to figure out how to get it to return words from other lines in the file.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define num_strings 20
#define size_strings 20
int *read_file(){
int j = 0;
static char text[num_strings][size_strings];
FILE *fp;
int x;
fp = fopen("dictionary2.txt", "r");
char s[100];
while(!feof(fp)) {
x = fscanf(fp,"%[^\n]",s);
fgetc(fp);
if (x==1) {
strcpy(text[j],s);
j++;
}
}
return text;
}
int main() {
int *p;
p = read_file();
int i;
for(i = 0; i < 10; i++) {
printf("%d:[%s]\n",i,*(p+i));
}
return(0);
}
In general, you should be creating your array in main() and passing it in, this kind of behavior is very unorthodox. However, if you do insist on doing it this way, you have to return a pointer to your array, since you cannot return arrays in C.
This is the kind of thing you'll need:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define num_strings 20
#define size_strings 20
typedef char (*PARR)[num_strings][size_strings];
PARR read_file(int * wordsread)
{
static char text[num_strings][size_strings];
FILE *fp;
if ( (fp = fopen("dictionary2.txt", "r")) == NULL ) {
fprintf(stderr, "Couldn't open file for reading\n");
exit(EXIT_FAILURE);
}
char s[100];
int j = 0;
while ( j < num_strings && fgets(s, sizeof s, fp) ) {
const size_t sl = strlen(s);
if ( s[sl - 1] == '\n' ) {
s[sl - 1] = 0;
}
if ( (strlen(s) + 1) > size_strings ) {
fprintf(stderr, "String [%s] too long!\n", s);
exit(EXIT_FAILURE);
}
strcpy(text[j++], s);
}
fclose(fp);
*wordsread = j;
return &text;
}
int main(void)
{
int wordsread = 0;
PARR p = read_file(&wordsread);
for ( int i = 0; i < wordsread; ++i ) {
printf("%d:[%s]\n", i, (*p)[i]);
}
return 0;
}
which, with a suitable input file, outputs:
paul#horus:~/src/sandbox$ ./twoarr
0:[these]
1:[are]
2:[some]
3:[words]
4:[and]
5:[here]
6:[are]
7:[some]
8:[more]
9:[the]
10:[total]
11:[number]
12:[of]
13:[words]
14:[in]
15:[this]
16:[file]
17:[is]
18:[twenty]
19:[s'right]
paul#horus:~/src/sandbox$
Note this only works because you declared your array in read_file() as static - don't return pointers to local variables with automatic storage duration in this way.
Try moving your #defines back and changing your function header to return a pointer to arrays of size_strings characters, as follows:
#define num_strings 20
#define size_strings 20
char (*read_file())[size_strings] {
Or alternately, with a typedef:
#define num_strings 20
#define size_strings 20
typedef char (*PCharArr)[size_strings];
PCharArr read_file() {
...and change the type of p in main accordingly:
char (*p)[size_strings];
That will return (a pointer to the first element of) an array of character arrays, which is more or less equivalent to a 2D array of char.
Update, oh I see, you pasted the code from main to the function, I know what happened here, you assumed p[20][20] is the same as a p* or maybe a p**, that's not correct, since now if you do *(p+1), the compiler doesn't know each element in p is 20 wide instead of 1 wide. You approach here should be to declare a pointer to an array of strings in read_file and return that instead:
static char text[num_strings][size_strings];
static char *texts[num_strings]
...
while....
....
if (x==1)
{strcpy(text[j],s);texts[j]=text[j];j++;}
return texts;
your p should be char* not int*. You also need to terminate the loop if 20 items have been read in.

Read file .txt and save it to struct in c

I want to ask about file processing and struct in C language, I get an assignment from my lecture, and am so really confused about string manipulation in C programming. Here is the task.
get data from mhs.txt
store in struct
sort by name ascending
Here is the mhs.txt
1701289436#ANDI#1982
1701317124#WILSON#1972
1701331734#CHRISTOPHER STANLEY#1963
1701331652#SHINVANNI THEODORE#1962
1701331141#MUHAMMAD IMDAAD ZAKARIA#1953
1701331564#MARCELLO GENESIS DRIET J.#1942
1701322282#ANANDA AULIA#1972
1701329175#LORIS TUJIBA SOEJONOPOETRO#1983
1701301422#DEWI JULITA#1993
1701332610#HARRY HUTALIANG#1982
first before # is NIM,
after first # is name
and the last after #, is year
and here is what i've done
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct student{
char nim[11];
char name[50];
int year;
}s[10];
int main(){
FILE *fp;
int c,i,n;
printf("Read mhs.txt...");
getchar();
fp = fopen("mhs.txt", "r");
c = getc(fp);
i = 0;
while(c!=EOF){
printf("%c", c);
c = getc(fp);
i++;
}
fclose(fp);
getchar();
return 0;
}
First thing, I could save data on struct, but in here I very confused to separate a string.
That's all I know about struct and file processing, is there anyone who can help me? I have traveled around the internet and could not find the correct results.
Sorry if there are duplicate questions, and sorry if my english is too bad.
This is pure C code, you should new three import function: strtok & qsort & fsan.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct student
{
char nim[11];
char name[50];
int year;
};
#define BUFFER_SIZE 100
struct student saveToStruct (char* str)
{
struct student res;
int flag = 0;
char *token = strtok(str, "#");
while( token != NULL )
{
if (0 == flag)
strcpy(res.nim, token);
else if (1 == flag)
strcpy(res.name, token);
else
res.year = atoi(token);
flag++;
token = strtok( NULL, "#" );
}
return res;
}
void print(struct student* arr, int size)
{
for (int i = 0; i < size; i++)
{
printf("%s, %s, %d\n", arr[i].nim, arr[i].name, arr[i].year);
}
}
int cmp(const void* l, const void* r)
{
return strcmp(((const student*)l)->name, ((const student*)r)->name);
}
int main()
{
struct student arr[10];
FILE* file = fopen("mhs.txt", "r");
if (!file)
return -1;
char buffer[BUFFER_SIZE];
int flag = 0;
while (fgets(buffer, BUFFER_SIZE, file))
{
arr[flag] = saveToStruct(buffer);
flag++;
}
print(arr, 10);
qsort(arr, 10, sizeof(struct student), cmp);
printf("After sort by name!\n");
print(arr, 10);
return 0;
}
Since you've tagged this as C++, I'd use C++:
#include <iostream>
#include <string>
#include <algorithm>
struct student {
std::string nim;
std::string name;
int year;
bool operator<(student const &other) {
return name < other.name;
}
friend std::istream &operator>>(std::istream &is, student &s) {
std::getline(is, s.nim, '#');
std::getline(is, s.name, '#');
return is >> s.year;
}
};
int main() {
std::ifstream in("mhs.txt");
std::vector<student> students{
std::istream_iterator<student>(in),
std::istream_iterator<student>()
};
std::sort(students.begin(), students.end());
}
If you want to accomplish roughly the same thing in C, it's probably easiest to do the reading with fscanf using a scanset conversion, like:
fscanf(infile, "%10[^#]#%49[^#]#%d", student.nim, student.name, &student.year);
The scanset conversion gives you something like a subset of regular expressions, so the %[^#] converts a string of characters up to (but not including) a #. In this case, I've limited the length of each to one less than the length you gave for the arrays in your struct definition to prevent buffer overruns.
Then you can do the sorting with qsort. You'll need to write a comparison function, and doing that correctly isn't always obvious though:
int cmp(void const *aa, void const *bb) {
student const *a = aa;
student const *b = bb;
return strcmp(a->name, b->name);
}
Here are some hints, not the full answer. Hope it could help you.
first you need to read the file line by line, instead of character by character. You need the function of fgets(). you may find the reference from www.cplusplus.com/reference/cstdio/fgets/
second you can use strtok() to seperate strings. here is an example.
char str[] = "now # is the time for all # good men to come to the # aid of their country";
char delims[] = "#";
char *result = NULL;
result = strtok( str, delims );
while( result != NULL ) {
printf( "result is \"%s\"\n", result );
result = strtok( NULL, delims );
}
and you may find the reference to strtok() from http://www.cplusplus.com/reference/cstring/strtok/
third, use qsort() to sort the structure array. you may find the reference of it from http://www.cplusplus.com/reference/cstdlib/qsort/. examples can also be found there.

Resources