C language: Copying strings one by one to an array - c

I have been trying for hours to try and make this work, but the result was always the same-error and program not responding.
This file represents chat history and I select the username from every line. Now I want to add them into an array, so that I can later on count them for example.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char* argv[])
{
char const* const fileName = argv[1];
FILE* file = fopen("beispielhafteGeschichte3", "r");
char line[256];
int i, j, k;
char new_array[15][30];
while (fgets(line, sizeof(line), file))
{
for (i=0; i<strlen(line); i++)
{
if (line[i-1]==']')
{
for(k=i; k<strlen(line); k++)
{
printf("%c", line[k]);
if (line[k+1]==':') break;
}
strncpy(new_array[i], line[k], 29); // ?????
printf("\n");
}
}
}
fclose(file);
return 0;
}
How to fix strncpy?

for (i=0; i<strlen(line); i++)
{
if (line[i-1]==']')
The first time through the loop, i will be zero and you'll attempt to access line[-1] which invokes undefined behaviour

line[k] is a char type, while the prototype for the strncpy function is:
char *strncpy(char *dest, const char *src, size_t n)
You should try edit your code like this:
strncpy(new_array[i], line+k, 29);

Related

Is there a way combine a specific number of chars from fgetc?

I have found some information about strcat and experimented with it but it doesn't work the way i expected for example :
char a = 'a', b = 'b';
strcat(a,b);
printf("%c", a);
this will produce an error "initialization of 'char' from 'char *' makes integer from pointer without a cast". Is there a way to unite chars until the wanted word is complete and store it in 1 variable? Or am i going completely wrong about this. The purpose of the code is to read an xml file and build a tree with the tags.
Any help is or advice is very much appreciated.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
int count = 0;
char c, word;
FILE *file = fopen("example.xml", "r");
if (file == NULL) {
return 0;
}
do {
c = fgetc(file);
if (c == '<') {
count = 1;
}
if (c == '>') {
count = 0;
printf(">");
}
if (count == 1) {
printf("%c", c);
}
if (feof(file)){
break ;
}
} while(1);
fclose(file);
return(0);
}
I'm not sure exactly what you're trying to accomplish, but you could try something like the following, which will print every <tag>, i.e., every string in the file between <...>'s , and will also accumulate them in an array of strings called tags[]. And note that you'd might want to add checks that avoid going over the 99 chars/tag and 999 tags total. But if this isn't anything like what you're actually trying to do, maybe clarify the question.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
int ntags=0, ichar=0,nchars=0;
char c='\000', tags[999][99];
FILE *file = fopen("example.xml","r");
if (file==NULL) return(0);
while((ichar=fgetc(file))!=EOF) {
c = (char)ichar;
if (nchars==0 && c!='<') continue;
tags[ntags][nchars++] = c;
if (c=='>') {
tags[ntags][nchars] = '\000';
printf("tag#%d = %s\n",ntags+1,tags[ntags]);
nchars=0; ntags++; }
}
/* do you now want to do anything with your tags[] ??? */
fclose(file);
return(0);
}
You are trying to use a function, those parameters are char *
char *strcat(char *dest, const char *src)
but you gave strcat a char but it wants a char*
int main()
{
char str1[20] = "this";
char str2[] = "is";
strcat(str1, str2);
printf("%s", str1);
return 0;
}
this is the way i thinkt you want it

strstr char array inside struct array

I have a struct defined as;
struct player {
int no, age;
char name[20];
} players[10];
Array is filled from file. What I try to do is, take input from user, add input to char array, send it to search(char lookup[]) function and strstr name field in a loop.
EDİT: Sorry I corrected the order. I'm trying to strstr in a loop.
char *p = strstr(players[x].name, inputFromUser);
but p is always null. How can I do this?
Thanks in advance.
EDIT - Code Added...
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
struct player {
int no, age;
char name[20];
} players[20];
void fillstruct(char *);
void search(char []);
int main(int argc, char *argv[])
{
int arg;
int c;
int d;
int i=0;
char a[100];
char *filename = NULL;
while((arg=getopt(argc, argv, "f:"))!=-1)
{
switch(arg)
{
case 'f':
filename = optarg;
fillstruct(filename);
break;
default:
break;
}
}
while((c=fgetc(stdin))!=EOF)
{
if(c!=10)
{
a[i]=c;
i++;
}
else
{
a[i]='\0';
search(a);
i=0;
}
}
return 0;
}
void search(char a[])
{
int i=0;
int col;
int found=0;
char *p =NULL;
while((i<20)&&(found==0))
{
p = strstr(a, players[i].name);
if(p)
{
col = p-a;
printf("\nPlayer '%s' found in '%s'.. Found index: %d", a, players[i].name, col);
found=1;
}
else
{
printf("\np=%s a=%s player[%d].name=%s", p, a, i, players[i].name);
}
i++;
}
}
void fillstruct(char *name)
{
FILE *fp;
char line[100];
int i=0;
fp = fopen(name, "r");
if(fp==NULL)
{
exit(1);
}
while(fgets(line, 100, fp)!=NULL)
{
players[i].no=i;
strcpy(players[i].name, line);
fprintf(stdout, "\nplayer=%s", players[i].name);
players[i].age=20;
i++;
}
fclose(fp);
}
Added as answer as suggested by mic_e
Assuming you're trying to search for a player name using the input from a user, you have the arguments of strstr in the reverse order. Also note that strstr is case sensitive.
char *p = strstr(players[x].name, inputFromUser);
fgets stores the \n and then stops taking input.
So suppose a player name is "user", players[i].name will be equal to "user\n" while a is "user".
So return of strstr is always NULL.
Try this instead:
p = strstr(players[i].name,a);
OR, remove the \n after taking input from file by fgets:
while(fgets(line, 100, fp)!=NULL)
{
players[i].no=i;
strcpy(players[i].name, line);
players[i].name[strlen(players[i].name)-1]='\0'; //add this line
fprintf(stdout, "\nplayer=%s", players[i].name);
players[i].age=20;
i++;
}
Like this:
char *p = strstr(players[x].name, inputFromUser);
It should work, It's fail if your input is wrong let me expalain in simple
int main()
{
char *ret;
char mystr[]="stack";
char str[]="This is stack over flow string";
ret = strstr(str, mystr);
printf("The substring is: %s\n", ret);
return(0);
}
Output is
The substring is: stack over flow string
That means
This function returns a pointer to the first occurrence in str of any of the entire sequence of characters specified in mystr, or a null pointer if the sequence is not present in str.
It case sensitive function means if try to search like
char mystr[]="Stack";//Note here first char is capital
And you got output like
The substring is: (null)
You can check your input and target string at your side by just printing content of it and verify it's correct or not.
printf("str1:%s str2:%s\n",players[x].name,inputFromUser)
char *p = strstr(players[x].name, inputFromUser);
I hope this clear your doubts.
That Should Work.
I think You have the problem with file reading Which fills the data array.
Please make sure that data you filled into structure is Ok.
And strstr returns address of the first Occurrence of the string1 in string2
where,
strstr(string2, string1);

C read colon delimited text file

The code reads a text file delimited by colons : and formatted as follows
1111:2222:3333
How would I store the values separated by colons : into separate variables ?
any help would be appreciated.
program code:
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
int read_file();
int main()
{
read_file(); // calls function to read file
return 0;
}
// read text file function
int read_file()
{
char line[100];
char file_location[40];
FILE *p_file;
printf("Enter file location: ");
scanf("%s",file_location);
p_file =fopen(file_location, "r");
if(!p_file)
{
printf("\n File missing:");
return 0;
}
while(fgets(line,100,p_file)!=NULL)
{
printf("%s \n",line);
}
fclose(p_file);
return 0;
}
This will give you a hint :
Use strtok as you would do for reading a csv file
while(fgets(line,100,p_file) != NULL)
{
char *p = strtok(line, ":");
while(p)
{
printf("%s\n", p); //Store into array or variables
p=strtok(NULL, ":");
}
}
POW already gave you everything you need to know.
So, FWIW:
One of the things C coders do is to keep a library of simple utitlies. Whacking a string up using delimiters is one of those utilities.
Here is a very simple (no error checking) example:
char **split(char **r, char *w, const char *src, char *delim)
{
int i=0;
char *p=NULL;
w=strdup(src); // use w as the sacrificial string
for(p=strtok(w, delim); p; p=strtok(NULL, delim) )
{
r[i++]=p;
r[i]=NULL;
}
return r;
}
int main()
{
char test[164]={0x0};
char *w=NULL; // keep test whole; strtok() destroys its argument string
char *r[10]={NULL};
int i=0;
strcpy(test,"1:2:3:4:hi there:5");
split(r, w, test, ":\n"); // no \n wanted in last array element
while(r[i]) printf("value='%s'\n", r[i++]);
printf("w='%s' test is ok='%s'\n",
(w==NULL)? "NULL" : w, test);// test is still usable
free(w); // w is no longer needed
return 0;
}

I need to know how many times a string appears within another one! Using C

Well, the title already says what I need. I tried to use a loop but it didn't go well, so, I came for your help guys!
Here's my code:
#include <stdio.h>
#include <stdlib.h>
int main()
{
char word[31], word2[31];
int size1, size2;
int i, j, k; // control
int count = 0;
printf ("\nInput the first word");
scanf ("%s", word);
printf ("\nInput the second word: ");
scanf (" %s", word2);
// I tried to make a loop through the first string and if it matches a letter, it would loop through the others (if they are equal, we have a substring), but failed to put it on the `for` loop
printf ("'%s' appears %d times within '%s'", word2, count, word);
return 0;
}
strstr is a useful function, it shortens your code considerably; when you find a match, just try again with the rest of the string;
#include <string.h>
#include <stdio.h>
int main()
{
const char* source = "aabaa";
const char* string2find = "aa";
int occurrences;
const char *ptr, *lastfind = NULL;
for(ptr=source; (lastfind=strstr(ptr, string2find)); ptr=lastfind+1)
occurrences++;
printf("%d\n", occurrences);
return 0;
}
...or if you're really set on doing it without string.h functions, the code gets a bit more verbose;
#include <string.h>
#include <stdio.h>
int main()
{
const char* source = "aaabaa";
const char* string2find = "aa";
int count=0;
const char *position;
for(position=source; *position; position++) {
int comparepos, equal=1;
for(comparepos=0; string2find[comparepos]; comparepos++) {
if(position[comparepos] != string2find[comparepos]) {
equal = 0;
break;
}
}
count+=equal;
}
printf("%d\n", count);
return 0;
}
Use strstr to find occurence of string in other string:
#include <stdio.h>
#include <string.h>
int main () {
char* a = "aaaa";
char* b = "aa";
char* c;
int count = 0;
for(c = a; *c; c++){
if(strstr(c, b)){
count++;
}
}
printf("count %d\n", count);
}
Also, use strlen to find length of a string..

Printing a C string in reverse without using pointers?

Is there a way to print a string of fixed size in reverse without using pointers?
#include<stdio.h>
main()
{
char buffer[10];
scanf("%s", buffer);
// need to print buffer in reverse without using pointers??
}
A lovely K&R function to reverse your string in-place before printing it, perhaps?
#include <stdio.h>
#include <string.h>
void strrev(char *s) {
int tmp, i, j;
for (i = 0, j = strlen(s) - 1; i < j; i++, j--) {
tmp = s[i];
s[i] = s[j];
s[j] = tmp;
}
}
int main(int argc, const char *argv[]) {
char buffer[10];
scanf("%s", buffer);
strrev(buffer);
printf("%s\n", buffer);
return 0;
}
#include<stdio.h>
main()
{
char buffer[10];
int n = scanf("%s", buffer);
// print the number of chars written to buffer
if (n != EOF) {
int len = strlen(buffer);
if (len <= 10) {
int i;
for (i = len - 1; i >= 0; i--)
printf("%c", buffer[i]);
}
}
}
Since [] is just syntactic sugar for pointers, here's a version that works completely without pointers, arrays or anything else, just one single int. You didn't say that the string has to be stored somehow. :) (Note that I use fgetc instead of a buffer and scanf).
[jkramer/sgi5k:.../c]# cat rev.c
#include <stdio.h>
#include <stdlib.h>
void read_print();
int main(void) {
fputs("Enter your string, yo! ", stdout);
read_print();
fputs("\nDone!\n", stdout);
return EXIT_SUCCESS;
}
void read_print() {
int c = fgetc(stdin);
if(c != EOF && c != '\n') {
read_print();
fputc(c, stdout);
}
}
[jkramer/sgi5k:.../c]# gcc -o rev rev.c -Wall -W -Os
[jkramer/sgi5k:.../c]# ./rev
Enter your string, yo! foobar
raboof
Done!
Here's a recursive way of doing it; technically, this is using a pointer, but I wouldn't go into language-lawyer mode with such simple tasks.
#include <stdio.h>
/* If you want it printed forward, or backward, or think of another way.. */
typedef enum {
FRONT = 1,
BACK,
} direction;
/* Technically still using a pointer...don't nitpick. */
void echo_string(char buffer[], size_t buflen, direction from)
{
/* An index into the buffer to echo, which will preserve
* its value across subsequent recursive calls.
*/
static size_t index = 0;
/* According to the specified direction, print from the front
* or the back of the buffer. Advance the index (a misnomer, I guess).
*/
if(from == FRONT) {
printf("%c", buffer[index++]);
}
else {
printf("%c", buffer[buflen - ++index]);
}
/* Are there any more characters to echo? Yes? Awesome! */
if(index != buflen) {
echo_string(buffer, buflen, from);
}
}
int main(int argc, char **argv)
{
char buffer[10];
scanf("%s", buffer);
/* Better strlen() than sizeof() here,
* but BEWARE! scanf() is DANGEROUS!
*/
echo_string(buffer, strlen(buffer), BACK);
return(0);
}
reverse(char c[], int len)
{
if( ! (len / 2))
return;
char t = c[0];
c[0] = c[len--];
c[len] = t;
reverse(c, len-1);
}
The error(s) is left as an exercise to the student.
As caf pointed out, we're still using pointers..!
Here's an other way to solve the problem (of reversing a string).
This code snippet (and probably most others) don't respect stuff like utf8. I think signines post demonstrating the K&R way was quite close to mine (:D) so I adapted mine to fit that example (and corrected some things..)
#include <stdio.h>
#include <string.h>
void strrev(char *s) {
size_t len = strlen(s) + 1;
size_t i, j;
for(i = 0; i < len / 2; i++) {
j = len-1 - i-1;
char tmp = s[j];
s[j] = s[i];
s[i] = tmp;
}
}
int main(int argc, const char *argv[]) {
char buffer[10];
scanf("%s", buffer); // Look out for an overflow ;)
strrev(buffer);
puts(buffer);
return(0);
}
You can use strrev to reverse a string.
#include <stdio.h>
#include <string.h>
main()
{
char buffer[10];
scanf("%s", buffer);
strrev(buffer);
printf("%s", buffer);
}
void outstrreverse(const char s[])
{
size_t l=strlen(s);
while( l && s!=&s[--l] )
putchar(s[l]);
if(s[0])
putchar(s[0]);
}
Because of the relationship between C strings, arrays, and pointers the exercise is rather shotty IMHO - the most idiomatic description of a "String" in C is represented by the char*, which is not an array. Your (the OPs) title and post differ in their definitions between string and char[fixed length].
The OP should read and understand this FAQ entry, and between that and the posts here: easily figure out a solution—as well as defend it to the teacher/judge if need be.
I'll comment on this: never use scanf("%s", buffer) to populate a fixed length string. If you must use scanf() to do it, please use a field width specifier: e.g. scanf("%9s", buffer); if buffer is an [10], you want a specifier of 9 because of how scanf fills the buffer: otherwise you must beware the dragons! You could also scanf by character and evade the issue with a loops bounds, but that would likely be less efficient.
#include <stdio.h>
#include <conio.h>
void reverse(char a[], int s, int sc );
void reverse(char a[], int s, int sc ){
if ((sc-s)<(s-1))
{
a[sc-s]^=a[s-1];
a[s-1]^=a[sc-s];
a[sc-s]^=a[s-1];
reverse (a, s-1, sc) ;
}
}
void main (){
char a[]="ABCDEFG";
reverse(a, 7, 7);
printf("%d",a);
getch(); //i just use it to freeze the screen
}

Resources