I am trying to teach myself C,so I am writing a program to see if a string is present at the end of another string.
#include <stdio.h>
#include <stdlib.h>
int containsAtEnd(char *s, char *t);
int strlen(char *s);
int main()
{
char *x = "tacocat";
char *y = "bol";
printf("%d\n", strend(x, y));
getchar();
return 0;
}
int strlen(char *s)
{
int i;
for (i = 0; i != '\0'; ++i)
;
printf("%d", i);
return i;
}
int containsAtEnd(char *s, char *t)
{
int tlen = strlen(*t);
int slen = strlen(*s);
int i = 0;
s += slen - tlen;
while ((*s == *t) && *s != '\0')
i++; s++; t++;
if (i < (tlen-1))
return 0;
else
return 1;
}
Yet, regardless of the strings given in the main function, "001" is always printed, indicating that the length of both the strings in 0 and the second string is present in the first.
Please try if the following code can help you. I would also advice you to use an IDE or an analysis program that tells you about taking pointer from integer without a cast and conditions that are always true (or always false).
#include <stdio.h>
int containsAtEnd(char *s, char *t);
int strlen(char *s);
int strlen(char *s)
{
int i;
for (i = 0; s[i] != '\0'; ++i)
;
printf("%d", i);
return i;
}
int containsAtEnd(char *s, char *t)
{
int tlen = strlen(t);
int slen = strlen(s);
int i = 0;
s += slen - tlen;
while ((*s == *t) && *s != '\0') {
i++; s++; t++;
}
if (i < (tlen-1))
return 0;
else
return 1;
}
int main()
{
char *x = "tacocat";
char *y = "bol";
printf("%d\n", containsAtEnd(x, y));
char *x2 = "foobarbaz";
char *y2 = "bar";
printf("%d\n", containsAtEnd(x2, y2));
getchar();
return 0;
}
Related
I have a problem removing a substring xx:xx:xx:xx:xx:xx from one main string. Here is the background info for the problem:
in a function void funA():
void funA(const char* sth){
if (sth == THINGA){
// do A;
}
else if (sth == THINGB){
// do B;
}
eles{
// do C;
}
log_status("current status: - %s", sth);
}
sth is a string contains a substring in the format of xx:xx:xx:xx:xx:xx where x is either a number or a letter. The substring has a space in front of it but might not have one at the end of the string. I need to obfuscate this substring with a *. Since only the substring has :, I made a helper function to locate the first : and the last : and remove 2 characters before it. Delete the last 2 characters and append a *. I think this way is most the best solution. So I'm wondering if there are any more efficient design of a helper function aka a helper function has shorter runtime and uses less memory. Since the substring xx:xx:xx:xx:xx:xx has a very distinguish format, the only easier way I can think of is to do a string match to find the substring and then replace it with a *. I'm open to other more innovative way though.
#ifndef PARSER_STACK_H_INCLUDED
#define PARSER_STACK_H_INCLUDED
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define PATTERN_LEN 18
typedef struct{
unsigned int start;
unsigned int finish;
}index;
void remove_str_pattern(char *original, char *extract, unsigned int start, unsigned int finish);
void splitter(char *x, index *index_SF);
unsigned int count_points(const char *x);
void obscure(char *str, index index_SF);
char* return_obscure_string(char *str);
char* return_pattern(char *str);
char* return_pattern(char *str){
index index_SF = {0,0};
char *str_export = calloc(PATTERN_LEN, sizeof(char));
char *tmp = calloc(sizeof(str)/sizeof(char), sizeof(char));
strcpy(tmp, str);
splitter(str, &index_SF);
obscure(tmp, index_SF);
remove_str_pattern(str, str_export, index_SF.start, index_SF.finish);
return str_export;
}
char* return_obscure_string(char *str){
index index_SF = {0,0};
char *str_export = calloc(PATTERN_LEN, sizeof(char));
char *tmp = calloc(sizeof(str)/sizeof(char), sizeof(char));
strcpy(tmp, str);
splitter(str, &index_SF);
obscure(tmp, index_SF);
remove_str_pattern(str, str_export, index_SF.start, index_SF.finish);
return tmp;
}
void obscure(char *str, index index_SF){
for(unsigned int i = index_SF.start; i < index_SF.finish+1; ++i){
if(str[i] != ':'){
str[i] = '*';
}
}
}
void splitter(char *x, index *index_SF){
for(unsigned int i = 0, tmp = 0; i < strlen(x); ++i){
if(x[i] == ':'){
++tmp;
if(tmp == 1){
index_SF->start = i-2;
}else{
if(tmp == 5){
index_SF->finish = i+2;
}
}
}
}
}
unsigned int count_points(const char *x){
int c = 1;
for(unsigned int i = 0; i < strlen(x); ++i){
if((x[i] == ':' && x[i+2] == ':') || (x[i] == ':' && x[i-2] == ':')){
++c;
}
}
return c;
}
void remove_str_pattern(char *original, char *extract, unsigned int start, unsigned int finish){
for(unsigned int i = start, j = 0; i < finish+1; ++i, ++j){
extract[j] = original[i];
}
}
#endif // PARSER_STACK_H_INCLUDED
That is my personal header file for your request, create header file with this code and try it ! :D
Two "main" functions of this file are.
1. char* return_obscure_string(char *str);
For return original string with obscured sub-string..
2. char* return_pattern(char *str);
For return pattern value from a string..
Good Luck Man !
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define PATTERN_LEN 18
typedef struct{
unsigned int start;
unsigned int finish;
}index;
void remove_str_pattern(char *original, char *extract, unsigned int start, unsigned int finish);
void splitter(char *x, index *index_SF);
unsigned int count_points(const char *x);
void obscure(char *str, index index_SF);
void main(){
index index_SF = {0,0};
char *origin = "this is first try for me in stack aa:bb:22:44:55:66 overflow...";
char *str_export = calloc(PATTERN_LEN, sizeof(char));
char *tmp = calloc(sizeof(origin)/sizeof(char), sizeof(char));
strcpy(tmp, origin);
splitter(origin, &index_SF);
obscure(tmp, index_SF);
remove_str_pattern(origin, str_export, index_SF.start, index_SF.finish);
printf("start index: %u finish index: %u\n", index_SF.start, index_SF.finish);
printf("obscured string %s\n", tmp);
printf("original str: %s\n", origin);
printf("pattern: %s\n", str_export);
}
void obscure(char *str, index index_SF){
for(unsigned int i = index_SF.start; i < index_SF.finish+1; ++i){
if(str[i] != ':'){
str[i] = '*';
}
}
}
void splitter(char *x, index *index_SF){
for(unsigned int i = 0, tmp = 0; i < strlen(x); ++i){
if(x[i] == ':'){
++tmp;
if(tmp == 1){
index_SF->start = i-2;
}else{
if(tmp == 5){
index_SF->finish = i+2;
}
}
}
}
}
unsigned int count_points(const char *x){
int count = 1;
for(unsigned int i = 0; i < strlen(x); ++i){
if((x[i] == ':' && x[i+2] == ':') || (x[i] == ':' && x[i-2] == ':')){
++count;
}
}
return count;
}
void remove_str_pattern(char *original, char *extract, unsigned int start, unsigned int finish){
for(unsigned int i = start, j = 0; i < finish+1; ++i, ++j){
extract[j] = original[i];
}
}
I've been programming a script where a string should be added to a string.
But the printf function in my code prints the first time □ the second time □□ and the third time □□□. It should print A,Ap, App.
Here's a quick overview of my code:
#include<stdio.h>
#include<stdlib.h>
int i = 0;
char * name[];
char * tok[];
int hello = 0;
void append(char* s, char c) {
int len = strlen(s);
s[len] = c;
s[len+1] = '\0';
}
int input(char data[]){
for(i=0; i<strlen(data); ++i){
append(tok, data[i]);
if(hello == 0){
append(name, tok);
strcpy(tok, "");
printf(name);
printf("\n");
}
}
return 0;
}
int main(){
input("App");
return 0;
}
The program has undefined behavior.
These tentative definitions
char * name[];
char * tok[];
in fact are equivalent to
char * name[1] = { NULL };
char * tok[1] = { NULL };
So for example this statement
int len = strlen(s);
invokes undefined behavior.
Or the function first parameter
void append(char* s, char c) {
and the supplied argument
append(tok, data[i]);
have different types. The type of the argument is char ** while the type of the parameter is char *.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int i = 0;
char name[99];
char tok[99];
int hello = 0;
void append(char *s, char c) {
int len = strlen(s);
s[len] = c;
s[len+1] = '\0';
}
int input(char *data){
for(i=0; i<strlen(data); ++i)
{
append(tok, data[i]);
printf(tok);
printf("\n");
}
return 0;
}
int main(){
input("App");
return 0;
}
I want to get all numbers from a specific string but, these numbers could be more than one digit long as (15, 587, ... exc). Here is what I did "my own code":
int firstIndxOfNumb(char* str, int startIndx, int len) {
int i, val;
i = startIndx;
while (str[i] && i < len) {
val = str[i];
if (isdigit(val))
return i;
i++;
}
return -1;
}
int lastIndxOfNumb(char* exp, int len, int indx1){
int i, curr;
for(i = indx1; i < len; i++){
curr = exp[i];
if(!isdigit(curr)){
return --i;
}
}
return 0;
}
int getNumb(char* exp, int len, int* indx1){
int indx2 = lastIndxOfNumb(exp, len, *indx1);
printf("indx1:%d\tindx2:%d\n", *indx1, indx2);
char temp[indx2-*indx1];
strncpy(temp, exp+*indx1, (size_t) (indx2-*indx1+1));
*indx1 = firstIndxOfNumb(exp, indx2+1, len);
return atoi(temp);
}
void main() {
char *s = "())(15*59";
int len = strlen(s);
int indx1;
indx1 = firstIndxOfNumb(s, 0, len);
printf("%d\n", getNumb(s, len, &indx1));
printf("\n%d", getNumb(s, len, &indx1));
}
And the goal is getting the two numbers (15, 59). The first call was okay but, the second is not "infinite-loop" with values index1:7 okay index2:0 isn't okay! Can you help me to make it working .....
The values are printed by printf(..); in getNum(); function ....
getNumb can be simplified as follows.
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
int getNumb(char **sp){
char *p = *sp;
while(*p && !isdigit((unsigned char)*p))//skip not digit
++p;
if(!*p)
return -1;//not find numbers (Don't include negative numbers as extract numbers)
int ret = strtol(p, &p, 10);
*sp = p;
return ret;
}
int main(void) {
char *s = "())(15*59";
char *sp = s;
printf("%d\n", getNumb(&sp));
printf("%d\n", getNumb(&sp));
}
When it contains a negative number.
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <stdbool.h>
bool getNum(char **sp, int *v /* out */){
char *p = *sp;
while(*p && !isdigit((unsigned char)*p) && (*p!='-' || !isdigit((unsigned char)p[1])) )//skip not number
++p;
if(!*p)
return false;//not find numbers
*v = strtol(p, &p, 10);
*sp = p;
return true;
}
int main(void) {
char *s = "())(15*59+++-123,-2)";
char *sp = s;
int v;
while(getNum(&sp, &v))
printf("%d\n", v);
}
ok so I am learning C and I try to use simple functions to understand basics and here I am stuck whith a segmentation fault I can't manage to make this code working h3lp please thanks you all !!!
#include <stdio.h>
#include <stdlib.h>
int ft_sqrt(int nb) //square root
{
unsigned int i;
i = nb;
while (nb < (i * i))
i--;
if (nb == (i * i))
return (i);
if (nb > (i * i))
return (0);
}
void ft_strcpy(char *d, char *s) // string copy
{
while((*d++ == *s++))
;
}
int ft_strlen(char *s) // string length
{
int i = 0;
while(s[i] != '\0')
i++;
return (i);
}
char *ft_itoa(int n) // integer to ascii
{
char *s;
s = (char *)malloc(99);
s += ft_strlen(s);
*s = 0;
while((*--s == n % 10 + '0') && (n /= 10))
;
return (s);
}
int ft_atoi(char *s) //ascii to integer
{
int i = 0;
while(*s)
i = 10 * i + *s++ - '0';
return (i);
}
int main()
{
int ft_sqrt(int nb);
void ft_strcpy(char *d, char *s);
char *ft_itoa(int n);
int ft_atoi(char *s);
int ft_strlen(char *s);
int a, *x;
a = 0;
char c[40], d[4];
c[40] = 0;
d[4] = 0;
a = ft_sqrt(1764); //42 in a
ft_strcpy(d, ft_itoa(a)); // a in d
ft_strcpy(c, "The square root of 1764 is: ");
x = ft_atoi(d);
printf("\n\n\t%s%sand%cin ascii\n\n\n", c, d, x);
return 0;
}
Just hack my code just wanna learn !!
There are many bugs in your code
When the nb is not a perfect square number, then it will give 0 always. Try it yourself. Use sqrt() instead (available under math.h header file)
Your ft_strcpy() is not properly framed, use strcpy() under string.h header file instead. Prototype : void strcpy(char *str1, char *str2),here the content of str2 will be copied to the str1.
char *ft_itoa(int n) may not properly work because you have provided wrong value to ft_strlen() which may turn out wrong value to be added to the pointer *s ( Why ?. Think your self , i'm not gonna tell you that elementary concept).
Do re-code your program and let me know if still can't fix the Error.
Hey #BLUEPIXY thanks for your help you fixed my atoi ! #psyco thank you here is my code fixed btw with the same value to ft_strlen() for *ft_itoa(int n).
#include <stdio.h>
#include <stdlib.h>
int ft_sqrt(int nb)
{
unsigned int i;
i = nb;
while (nb < (i * i))
i--;
if (nb = (i * i))
return (i);
if (nb > (i * i))
return (0);
}
void ft_strcpy(char *d, char *s)
{
while((*d++ = *s++))
;
}
int ft_strlen(char *s)
{
int i = 0;
while(s[i] != '\0')
i++;
return (i);
}
char *ft_itoa(int n)
{
char *s;
s = (char *)malloc(99);
s += ft_strlen(s);
*s = 0;
while((*--s = n % 10 + '0') && (n /= 10))
;
return (s);
}
int ft_atoi(char *s)
{
int i = 0;
while(*s)
i = 10 * i + *s++ - '0';
return (i);
}
int main()
{
int ft_sqrt(int nb);
void ft_strcpy(char *d, char *s);
char *ft_itoa(int n);
int ft_atoi(char *s);
int ft_strlen(char *s);
int a;
a = 0;
char c[40], d[4];
c[40] = 0;
d[4] = 0;
a = ft_sqrt(1764);
ft_strcpy(d, ft_itoa(a));
ft_strcpy(c, "The square root of 1764 is: ");
printf("\n\n\t%s%s and %c in ascii\n\n\n", c, d, ft_atoi(d));
return 0;
}
BugFixed thank you all
for exemple i need to invers "Paris" to "siraP"...
My main:
int main(void)
{
char w1[] = "Paris";
ReverseWord(w1);
printf("The new word is: %s",w1);
return0;
}
and my function:
void ReverseWord(char *Str)
{
int counter=0;
for(int i=0; *(Str+i)!='\0'; i++)
counter++;
int length = counter-1;
char temp[length];
for(int j=0; temp[j]=='\0'; j++)
temp[j]=Str[length-j];
}
Now I have my renverse word in temp[].
I need to put it in my pointer *Str.
How can I do it??
Thanks
If you want use temp must then your function like this
void ReverseWord(char *Str)
{
int i,j;
if(str)
{
int length=strlen(Str);
char temp[length+1];
for( j=0; j<length; j++)
temp[j]=Str[length-1-j];
temp[j]='\0';
strcpy(Str,temp);
}
}
Without using temp as follows
void ReverseWord(char *Str)
{
int end= strlen(Str)-1;
int start = 0;
while( start<end )
{
Str[start] ^= Str[end];
Str[end] ^= Str[start];
Str[start]^= Str[end];
++start;
--end;
}
}
void ReverseWord(char *Str)
{
size_t len;
char temp, *end;
len = strlen(Str);
if (len < 2)
return;
end = Str + len - 1;
while (end > Str)
{
temp = *end;
*end-- = *Str;
*Str++ = temp;
}
}
One more option, this time with dangerous malloc(3).
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char *rev(char s[]) {
char *buf = (char *)malloc(sizeof(char) * strlen(s));
int i, j;
if(buf != NULL)
for(i = 0, j = strlen(s) - 1; j >= 0; i++, j--)
buf[i] = s[j];
return buf;
}
int main(int argc, char **argv) {
printf("%s\n", rev(argv[1]));
return 0;
}
Run with "foo bar foobar baz" and get zab raboof rab oof back:
~/tmp$ ./a.out "foo bar foobar baz"
zab raboof rab oof
Here I think you can study two algorithms:
C string length calculate: the end of the c string is '\0'
How to reverse a c string in place
And if you need to test the code, you should alloc testing strings in heap or strack. If you write a literal string, you may meet a bus error because of the literal string being saved in text-area which is a read only memory.
And the following is the demo:
#include <stdio.h>
#include <stdlib.h>
void reverse_string(char* str)
{
size_t len;
char tmp, *s;
//Get the length of string, in C the last char of one string is \0
for(s=str;*s;++s) ;
len = s - str;
//Here we use the algorithm for reverse the char inplace.
//We only need a char tmp place for swap each char
s = str + len - 1;
while(s>str){
tmp = *s;
*s = *str;
*str = tmp;
s--;
str++;
}
}
int main()
{
char* a = "abcd";
//Here "abcd" will be saved in READ Only Memory. If you test code, you will get a bus error.
char* b = (char*)calloc(1,10);
strcpy(b,a);
reverse_string(b);
printf("%s\n",b);
a = "abcde";
strcpy(b,a);
reverse_string(b);
printf("%s\n",b);
}
you can do it simply by following code
for(int k=0;k<strlen(temp);k++)
{
Str[k]=temp[k];
}