I got some troubles while I'm trying to set a char into a char* ("string")
I got lines, which is all the txt lines I fetched before, and now I'm trying to assign a char to my char*, to filter it.
Here is my actual code :
void TreatDatas(char** lignes, int sizeLignes){ // all the lines, and the size of it.
char** finalArray;
finalArray = malloc(2048 * sizeof(char*));
int sizeOfFinalArray = 0;
int i;
int j;
char* s;
char* savedCurrentString = "";
int sizeOfCurrentString = 0;
for (i = 0; i< sizeLignes; i++){
s = lignes[i];
for (j = 0; j < strlen(s); j++){ // I don't pass the first condition the first loop
if (s[j] == ',' || s[j] == '.' || s[j] == ' ' || s[j] == '\n' || s[j] == ';' || s[j] == ':'){ // Separators list
finalArray[sizeOfFinalArray] = malloc(strlen(savedCurrentString) + 1);
strcpy(finalArray[sizeOfFinalArray], savedCurrentString);
savedCurrentString = "";
sizeOfCurrentString = 0;
}else{
printf("%c , %s \n", s[j], savedCurrentString); // L - ""
printf("%d", sizeOfCurrentString); // 0
strncpy(savedCurrentString, s[j], 1); // error here
}
}
}
free(finalArray);
}
Ok I change a bit the code, now it's better, but seems to duplicate some elements. And I don't know why. Excuse me, I'm a C beginer, but I'm curious and trying to understand how that works.
void TreatDatas(char** lignes, int sizeLignes){
char** finalArray;
finalArray = malloc(2048 * sizeof(char*));
int sizeOfFinalArray = 0;
int i;
int j;
char* s;
char* savedCurrentString = "";
int sizeOfCurrentString = 0;
for (i = 0; i< sizeLignes; i++){
s = lignes[i];
printf("line : %d \n %s \n", i, s);
StringSpliter(s);
// for (j = 0; j < strlen(s); j++){
// finalArray[sizeOfFinalArray] = malloc(strlen(savedCurrentString) + 1);
// }
}
free(finalArray);
}
char * StringSpliter(char* input){
char separators[5][2] = {" ", ",", ";", ":", "."};
char ** buffer;
int bufferSize = 0;
int i;
for (i = 0; i < 5; i++){
char* token = strtok(input, separators[i]);
printf("%s", token);
while( token != NULL )
{
printf( " %s\n", token );
token = strtok(NULL, separators[i]);
}
}
printf("\n");
return "OSEF";
}
My output
Related
I want to split my array and sort after it using bubble sort and srttok, from 'b' to 'z' it's all right, but when it comes to 'a' it has some problem.
Here's my code:
#include <stdio.h>
#include <string.h>
int main(int argc, char const *argv[]) {
char str[10000];
char *token[100] = { 0 };
const char s[5] = { ' ', ',', ';', ':', '.' };
gets(str);
int i = 0;
token[i] = strtok(str, s);
while (token[i] != NULL) {
i++;
token[i] = strtok(NULL, s);
}
for (int j = 0; j < i; j++) {
printf("%s\n", token[j]);
}
printf("i = %d\n", i);
char *temp;
int exchanged = 1;
for (int j = 0; exchanged && j < i - 1; j++) {
exchanged = 0;
for (int k = 0; k < i - 1 - j; k++) {
if (strcmp(token[k], token[k + 1]) > 0) {
temp = token[k];
token[k] = token[k + 1];
token[k + 1] = temp;
exchanged = 1;
}
}
}
printf("\nAfter sort\n");
for (int j = 0; j < 100; j++) {
printf("%s\n", token[j]);
}
printf("\n");
}
Here's my result
It works well when I type 'b' to 'z', and wrong when I type 'a', how did that happen?
The string of separators const char s[5] = { ' ', ',', ';', ':', '.' }; is not null terminated. Passing it to strtok() has undefined behavior.
If you use a brace enclosed initializer list, you must specify the null terminator either explicitly as:
const char s[] = { ' ', ',', ';', ':', '.', '\0' };
or implicitly by giving the array a length of 6 bytes:
const char s[6] = { ' ', ',', ';', ':', '.' };
But it is much simpler to define this string as:
const char s[] = " ,;:.";
Also note that gets() has been removed from the C Standard. You should not use this function. Use fgets() instead and add \n to the s string.
You should also test that i does not exceed the maximum index value in token to accessing elements beyond the array boundaries.
Here is a modified version:
#include <stdio.h>
#include <string.h>
int main(int argc, char const *argv[]) {
char str[10000];
char *token[100];
char *tok;
const char s[] = " ,;:.\n";
if (!fgets(str, sizeof str, stdin)) {
fprintf(stderr, "no input\n");
return 1;
}
int i = 0;
tok = strtok(str, s);
while (tok != NULL) {
if (i == 100) {
fprintf(stderr, "too many tokens at %s\n", tok);
break;
}
token[i++] = tok;
tok = strtok(NULL, s);
}
for (int j = 0; j < i; j++) {
printf("%s\n", token[j]);
}
printf("i = %d\n", i);
int exchanged = 1;
for (int j = 0; exchanged && j < i - 1; j++) {
exchanged = 0;
for (int k = 0; k < i - 1 - j; k++) {
if (strcmp(token[k], token[k + 1]) > 0) {
char *temp = token[k];
token[k] = token[k + 1];
token[k + 1] = temp;
exchanged = 1;
}
}
}
printf("\nAfter sort\n");
for (int j = 0; j < 100; j++) {
printf("%s\n", token[j]);
}
printf("\n");
return 0;
}
Note that all the tokens pointed to by the token string pointers are inside the str array. If you overwrite this array, for example with a second call to fgets(), the tokens will be corrupted. You can allocate separate strings to avoid this with:
token[i++] = strdup(tok);
To avoid memory leaks, you would free the memory using for (i = 0; i < j; i++) free(token[j]); before leaving the function.
I want to insert string to the array until I type "ok". Why I am getting just "ok" and original array at the output?
int main(void)
{
char b[20];
char* str[10] = { "1","2" };
int i = 2;
while (1) {
gets(b);
if (strcmp(b, "ok") == 0) break;
str[i] = b;
i++;
}
for (int j = 0; j < i; j++)
printf("%s ", str[j]);
return 0;
}
You need to allocate a string on each iteration:
int main(void)
{
char* b;
char* str[10] = { "1","2" };
int i = 2;
while (1) {
b = malloc(20);
gets(b);
if (strcmp(b, "ok") == 0) break;
str[i] = b;
i++;
}
for (int j = 0; j < i; j++)
printf("%s ", str[j]);
// free allocated strings
while (i > 2)
free(str[--i]);
return 0;
}
They all point to b, which gets overwritten in each iteration.
You need to create a copy of the string when you assign it:
str[i] = strdup(b);
You also may consider using fgets instead of gets; however, you will need to remove the newline:
size_t size;
fgets(str, 20, stdin);
size = strlen(str);
if(str[size-1] == '\n')
str[size-1] = '\0';
Also, print a newline at the end of your program, so it won't interfere with the shell:
putchar('\n');
Full code:
int main(void)
{
char b[20];
char* str[10] = { "1","2" };
int i = 2;
while (1) {
size_t size;
fgets(str, 20, stdin);
size = strlen(str);
if(str[size-1] == '\n')
str[size-1] = '\0';
if (strcmp(b, "ok") == 0)
break;
str[i] = strdup(b);
i++;
}
for (int j = 0; j < i; j++)
printf("%s ", str[j]);
putchar('\n');
return 0;
}
You need to make a copy of the input string, then save a pointer to the copy of the input string in your array. Something like:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
char b[20];
char *str[10] = { "1","2" };
int i = 2;
char *p;
size_t lenb;
for(i = 2 ; i < 10 ; ++i)
{
fgets(b, sizeof(b), stdin);
lenb = strlen(b);
if(lenb > 0 && *(b+lenb-1) == '\n')
{
*(b+lenb-1) = '\0'; /* overwrite the trailing \n */
lenb = strlen(b);
}
if (strcmp(b, "ok") == 0)
break;
p = malloc(lenb+1);
strcpy(p, b);
str[i] = p;
}
for (int j = 0; j < i; j++)
printf("%s\n", str[j]);
return 0;
}
I'm trying to make a program that takes in a database of listfile names and compare it with another list. When there is a match it should rename the file with that name to the corresponding relationNumber.
At the end of the code I try to rename the file, but it doesn't let me. Is it because I'm trying to pass chars instead of const chars? And if so, how can I solve this? Before I try to rename the file I printed the strings out to see what is in them and the strings contain; "Zaalstra legitimatie.txt" and "1.17234842.txt" which is what I want. Thanks in advance.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define relationLen 10
#define true 1
#define false 0
#define resetptr NULL
typedef int bool;
char* strcasestr(char* haystack, char* needle) {
size_t i, j;
if (!needle[0])
return (char*) haystack;
for (i = 0; haystack[i]; i++) {
bool matches = true;
for (j = 0; needle[j]; j++) {
if (!haystack[i + j])
return NULL;
if (tolower((unsigned char)needle[j]) != tolower((unsigned char)haystack[i + j])) {
matches = false;
break;
}
}
if (matches)
return (char *)(haystack + i);
}
return NULL;
}
int main(void) {
char database[1024][30];
char name[30] = {0};
char newName[30] = {0};
char extension[1024][5];
char lined[256], linef[256];
char relationNumber[] = "1.1";
char newRelationNumber[relationLen] = {0};
char *ret, *number;
int i, j, c, k, len = 0;
FILE* filef = fopen("filelist.txt", "r");
for(i = 0; (c = fgetc(filef)) != EOF; i++) {
fgets(linef, sizeof(linef), filef);
strcpy(database[i], (char[2]){(char) c, '\0'});
strcat(database[i], linef);
len = strlen(database[i]);
for(j = 0, k = 5; j < 4; j++, k--) {
extension[i][j] = database[i][len-k];
}
printf("%s ", extension[i]);
printf("%s", database[i]);
}
FILE* filed = fopen("Database.txt", "r");
fgets(lined, sizeof(lined), filed);
printf("%s", lined);
number = strstr(lined, relationNumber);
for(i = 0; lined[i] != 9; i++)
newName[i] = lined[i];
newName[i] = '\0';
for(i = 0; i < relationLen; i++)
newRelationNumber[i] = number[i];
newRelationNumber[i] = '\0';
number = resetptr;
strcat(newRelationNumber, ".txt");
ret = strcasestr(database[i], newName);
printf("%s", database[0]);
printf("%s", newRelationNumber);
i = rename(database[0], newRelationNumber);
printf("\n%d", i);
return 0;
}
*Can someone please help me with this function. I'm trying to separate the string input into tokens and also shift each token some by some specified amount. *
char *tokenize(char *f, int shift){
const char delim[] = " .;\n\t";
char *pa = f; //points to the beginning of *f
//size of *f
int i;
int stringSize = 0;
for(i = 0; f[i] != '\0'; i++)
{
stringSize++;
}
//put string in array to pass to strtok function
char newString[stringSize];
int j;
for(j = 0; j < stringSize; j++)
{
newString[j] = *f;
f++;
}
//break the words up into sub-strings without the delimiters
char *word = strtok(newString, delim);
while(word != NULL)
{
word = strtok(NULL, delim);
word = stringShift(word, shift);
//printf("After being shifted %d = %s\n", shift, word);
}
return pa;
}
/*Shift Function*/
char *stringShift(char *s, int k){
int i;
for(i = 0; s[i] != '\0'; i++)
{
s[i] += k;
}
return s;
}
I think this should serve the purpose ok, as far as I understand it
char* addWordToArr(char *arr,char *word)
{
int i;
for(i =0;i<strlen(word);i++)
{
*arr++ = word[i];
}
*arr++ = ' ';
return arr;
}
char *tokenize(char *f, int shift){
const char delim[] = " .;\n\t";
int stringSize = strlen(f);
//put string in array to pass to strtok function
char newString[stringSize+1];
int j;
for(j = 0; j < stringSize; j++)
{
newString[j] = *f;
f++;
}
newString[stringSize] = '\0'; //null terminate
char *rVal = malloc(sizeof(char) * (stringSize +1)); //The total length of the tokenized string must be <= the original string
char *writePtr = rVal;
//break the words up into sub-strings without the delimiters
char *word = strtok(newString, delim);
word = stringShift(word, shift);
writePtr = addWordToArr(writePtr,word);
while(word != NULL)
{
word = strtok(NULL, delim);
if(word)
{
word = stringShift(word, shift);
writePtr = addWordToArr(writePtr,word);
}
}
writePtr = '\0';
return rVal;
}
which produces:
string before shift bish;bash;bosh hyena trout llama exquisite underwater dinosaur
string after shift dkuj dcuj dquj j{gpc vtqwv nncoc gzswkukvg wpfgtycvgt fkpqucwt
The stringShift function is unchanged
It is sufficient to say that I am new to C so please have show some mercy ;).
I'm trying to compare two strings. The output shouldn't contain common characters. Sadly it does.
Here is the code:
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
const char msg[15] = "blueberry";
int c;
int s[15];
int j = 0;
int i = 0;
int k= 0;
int ok = 0;
int t = 0;
while (i < 15 && (c = getchar()) != '\n')
{
s[i] = c;
++i;
}
for (t=j=0; t < 15; ++t)
{
ok = 1;
//printf ("%c", s[t]);
}
for (k=0; msg[k] != '\0'; ++k)
{
if (s[t] == msg[k])
{
ok = 0;
}
}
if (ok == 1)
{
s[j] = s[t];
j++;
}
s[j] = '\0';
for (j = 0; j < 15; ++j)
printf ("%c ", s[j]);
}
The input from the keyboard is blackberry, expected output should've been U but sadly it is not. Any help please. Also why is it entering the nested for loop irrespective of condition?
My big thanks to everyone, it helped me a lot. I've figured out a way & am ok with the output. I've borrowed some ideas from A4L :).
To compare two string, you can use strcmp().
The following is a string compare program that you can use for your reference. I has both array and pointer version for better understanding.
#include <stdio.h>
int strcmp1(char a[], char b[])
{
int i=0;
while (a[i] == b[i]) {
if (a[i] == '\0')
return 0;
i++;
}
return a[i]-b[i];
}
int strcmp2(char *a, char *b)
{
while (*a == *b) {
if (*a == '\0')
return 0;
a++; b++;
}
return *a-*b;
}
int main()
{
char s1[] = "test string1";
char s2[] = "test string";
char s3[] = "aaa";
char s4[] = "bbb";
printf("strcmp1(%s, %s) = %d \n", s1, s2, strcmp1(s1, s2));
printf("strcmp2(%s, %s) = %d \n", s3, s4, strcmp2(s3, s4));
return 0;
}
given that msg contains "blueberry" and s contains "blackberry" this should do it
for (int i=0; i < strlen(msg); i++) {
for (int j = 0; j < strlen(s); j++) {
if (msg[i] != s[j]) {
printf ("%c", msg[i]);
}
}
}
yes it's ugly (using the strlen in the for gives me the chills, but I'm still low on coffeine today ^^)
i guess you want to find the first letter where the input differs from message
here is your own code with some fixes
#include <stdio.h>
#include <stdlib.h>
int main(void) {
const char msg[15] = "blueberry";
int c;
char s[15];
int i = 0;
int k= 0;
int ok = 0;
while (i < 15 && (c = getchar()) != '\n')
{
s[i] = (char) c;
++i;
}
// make sure to terminate the string after hitting enter
s[i] = '\0';
printf("input: %s\n", s);
printf("messg: %s\n", msg);
// run through both input and message with one counter
for (k=0; ok == 0 && msg[k] != '\0' && s[k] != '\0'; )
{
// if different chars stop
if (s[k] != msg[k]){
ok = 1;
} else {
// next char
k++;
}
}
if (ok == 1)
{
printf ("diff # index %d -> %c\n", k, msg[k]);
}
else
{
printf ("no diff\n");
}
return 0;
}
#include <stdio.h>
#include <string.h>
//Length to match
int comm(char* s1, char* s2){
int len = 0;
while(*s1 && *s2 && *s1++ == *s2++)
++len;
return len;
}
//commdiffcomm
/*
int commr(char* s1, char* s2){
int len = 0, limit;
int len1,len2;
len1 = strlen(s1);
len2 = strlen(s2);
limit = len1 > len2 ? len2 : len1;
s1 = s1 + len1;
s2 = s2 + len2;
while(limit-- && *--s1 == *--s2)
++len;
return len;
}
//bad
int diff(char* s1, char* s2, int* len1, int* len2){
int len, lenr, s1_len, s2_len, wk_max, i, j;
len = comm(s1, s2);
if(strcmp(s1, s2)==0){
*len1 = *len2 = 0;
return len;
}
lenr = commr(s1, s2);
*len1 = strlen(s1) - len - lenr;
*len2 = strlen(s2) - len - lenr;
return len;
}
*/
int diff(char* s1, char* s2, int* len1, int* len2){
int len, s1_len, s2_len, wk_max, i, j;
len = comm(s1, s2);
if(strcmp(s1, s2)==0){
*len1 = *len2 = 0;
return len;
}
s1_len = strlen(s1 + len + 1);
s2_len = strlen(s2 + len);
wk_max = 0;
for(i = 1; i < s1_len ; i++){
for(j = 0; j < s2_len; j++){
int com_len;
com_len = comm(s1 + len + i, s2 + len + j);
if(wk_max < com_len){
wk_max = com_len;
*len1 = i;
*len2 = j;
}
}
}
return len;
}
int main(){
char str1[16] = "blueberry";
char str2[16] = "blackberry";
char dif1[16] = "";
char dif2[16] = "";
int len0;//length of top to diff pos
int len1;
int len2;
len0 = diff(str1, str2, &len1, &len2);
strncpy(dif1, str1 + len0, len1);
strncpy(dif2, str2 + len0, len2);
if(len1 !=0 && len2 != 0){
printf("%s different %s at position %d length %d (\"%s\")\n", str1, str2, len0, len1, dif1);
printf("%s different %s at position %d length %d (\"%s\")\n", str2, str1, len0, len2, dif2);
} else {
printf("two string is same.");
}
return 0;
}
/*
blueberry different blackberry at position 2 length 2 ("ue")
blackberry different blueberry at position 2 length 3 ("ack")
*/
There are a few problems with the code as is:
You don't null-terminate your input string. Attempting to use it with c string functons would spell trouble. To fix that, change
while (i < 15 && (c = getchar()) != '\n')
{
s[i] = c;
++i;
}
to
while (i < 14 && (c = getchar()) != '\n')
{
s[i] = c;
++i;
}
s[i] = '\0';
Your specification is unclear as to whether you want your program to print the letters unique to msg, or to both s and msg. (i.e, do you want msg-s or (msg ∪ s)-(msg ∩ s) Assuming the first, the important part of your program goes like this:
k=0;
for(i=0;i<strlen(msg);i++){
int exists = 0;
for(j=0;!exists && j<strlen(s);j++){
if(msg[j] == s[i])
exists = 1;
}
if(!exists)
msg[k++] = msg[i];
}
s[k] = '\0';
The inner loop checks if s contains the current character in msg. If it does, we don't do anything, but if it doesn't, we append it to the end of a sublist we're creating on top of the bits of msg we've already processed.
your code is a mess even after the rewrite - there are too many errors to describe in detail
/*
blackbery
b l u e b e r r y
. . a c k b e . .
result = non-equal
*/
#include <stdio.h>
#include <stdlib.h>
int main(void) {
const char msg[15] = "blueberry";
int c, s[15], i,j,k, ok;
for (i=0; i < 15; i++) s[i] = 0;
for (i=0; i < 15 && (c = getchar()) != '\n'; i++) s[i] = c;
for (ok=1, k=0; msg[k] != '\0'; ++k)
if (s[k] != msg[k]) ok = 0; else s[k] = '.';
for (j = 0; j < 15; ++j) printf ("%c ", msg[j]);
printf("\n");
for (j = 0; j < 15; ++j) printf ("%c ", s[j]);
printf("\nresult = %s\n", ok ? "equal" : "non-equal");
}