Sequence of String and its Implementation - c

I have a little tiny trouble with implementing a shift. Here is the idea of what I'm trying to do:
Given a string of number like 012345, given a specific condition, the sequence will shift from
012345
001234.Can somebody show me why the code didn't work and how can I fix this.
for(int a = i; a < (strlen(input)); a++)
if (a < strlen(input) - 2)
{
holder = key[a+1];
key[a+1] = key[a];
key[a+2] = holder;
}
}

To shift right a string you can do:
#include <stdio.h>
#include <stdint.h>
#include <string.h>
void shift_r_str (char *string, size_t len, uint8_t shift);
int main(void)
{
char input[] = "012345";
shift_r_str(input, strlen(input), 1);
printf("Shifted: %s\n", input);
shift_r_str(input, strlen(input), 2);
printf("Shifted: %s\n", input);
}
void shift_r_str (char *string, size_t len, uint8_t shift)
{
size_t i;
if (len < shift)
{
shift = len;
}
for (i=len-1; ((i>0) && (i>=shift)); i--)
{
string[i] = string[i-shift];
}
for (i=0; i<shift; i++)
{
string[i] = '0';
}
}
Output will be:
Shifted: 001234
Shifted: 000012

Related

Need to sort a string input by the most frequent characters first in C (qsort)

I managed to sort it alphabetically but I need to sort it by the most frequent characters first after that. Since I'm new to C programming Im not sure if this alphabetical sort is needed. Also I thought about using a struct but not sure how to do the whole process with it.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int cmpfunc(const void *a, const void *b) {
return *(char*)a - *(char*)b;
}
void AlphabetOrder(char str[]) {
qsort(str, (size_t) strlen(str), (size_t) sizeof(char), cmpfunc);
printf("%s\n", str);
}
void Max_Occurring(char *str)
{
int i;
int max = 0;
int freq[256] = {0};
for(i = 0; str[i] != '\0'; i++)
{
freq[str[i]] = freq[str[i]] + 1;
}
for(i = 0; i < 256; i++)
{
if(freq[i] > freq[max])
{
max = i;
}
}
printf("Character '%c' appears %d times", max, freq[max], str);
}
int main() {
char str1[20];
printf("Enter a string: ");
scanf("%s", &str1);
AlphabetOrder(str1);
Max_Occurring(str1);
return 0;
}
I wrote you a frequency sorter using the idea that #WeatherVane mentioned:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct cfreq {
unsigned char c;
int freq;
};
int freqcmp(const void *a, const void *b) {
struct cfreq *a2 = (struct cfreq *) a;
struct cfreq *b2 = (struct cfreq *) b;
if(a2->freq < b2->freq) return -1;
if(a2->freq == b2->freq) return 0;
return 1;
}
int freqcmpdesc(const void *a, const void *b) {
return -freqcmp(a, b);
}
void FrequencyOrder(const char str[]) {
struct cfreq cfreqs[256];
for(int i = 0; i < sizeof(cfreqs) / sizeof(*cfreqs); i++) {
cfreqs[i].c = i;
cfreqs[i].freq = 0;
}
for(int i = 0; str[i]; i++) cfreqs[str[i]].freq++;
qsort(cfreqs, sizeof(cfreqs) / sizeof(*cfreqs), sizeof(*cfreqs), freqcmpdesc);
for(int i = 0; i < sizeof(cfreqs) / sizeof(*cfreqs); i++) {
if(cfreqs[i].freq) printf("%c", cfreqs[i].c);
}
printf("\n");
}
int main() {
char str1[20];
printf("Enter a string: ");
scanf("%s", &str1);
FrequencyOrder(str1);
return 0;
}
and here is a sample session (note: output is not deterministic for letters with same frequency):
Enter a string: buzz
zbu
If you want duplicate letters in the output then replace the print with a loop along these lines:
while(cfreqs[i].freq--) printf("%c", cfreqs[i].c);
Im not sure if this alphabetical sort is needed.
It is not needed, yet if done, Max_Occurring() can take advantage of a sorted string.
Since the string is sorted before calling Max_Occurring(), compute the max occurring via a count of adjacent repetitions of each char.
// Untested illustrative code.
// str points to a sorted string.
void Max_Occurring(const char *str) {
char max_ch = '\0';
size_t max_occurence = 0;
char previous = '\0';
size_t occurrence = 0;
while (*str) {
if (*str == previous) {
occurrence++;
} else {
occurrence = 1;
}
if (occurrence > max_occurence) {
max_occurence = occurrence;
max_ch = *str;
}
previous = *str;
str++;
}
printf("Character '%c' appears %zu times", max_ch, max_occurence);
}
In the case of multiple characters with the same max occurrence, this code only reports one max.
Avoid buffer overflow
Do not use scanf("%s"... without a width limit.
Tip: enable all warnings to save time and see the problem of using &str1 when str1 should be used.
char str1[20];
...
// scanf("%s", &str1);
scanf("%19s", str1);
Avoid a negative index
If still wanting to for a frequency table, watch out for the case when char is signed and code use str[i] < 0 to index an array.
Instead:
const unsigned char *ustr = (const unsigned char *) str;
size_t freq[UCHAR_MAX + 1] = {0};
for(size_t i = 0; ustr[i] != '\0'; i++) {
freq[ustr[i]]++;
}
Here's another alternative that may be simpler.
void freqOrder( char *p ) {
#define ASCIIcnt 128 // 7bit ASCII
// to count occurences of each character
int occur[ ASCIIcnt ];
memset( occur, 0, sizeof occur );
int maxCnt = 0; // remember the highest count
// do the counting
for( ; *p; p++ )
if( ++occur[ *p ] > maxCnt )
maxCnt = occur[ *p ];
// output most frequent to least frequen
for( ; maxCnt; maxCnt-- )
for( int i = 0; i < ASCIIcnt; i++ )
if( occur[i] == maxCnt )
while( occur[i]-- )
putchar( i );
putchar( '\n' );
}
int main( void ) {
freqOrder( "The quick brown fox jumps over the lazy dog" );
return 0;
}
Output
' ooooeeehhrruuTabcdfgijklmnpqstvwxyz'

C string manipulation for removing xx:xx:xx:xx:xx:xx

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];
}
}

How to convert to binary as string in code C

I am trying to convert int to binary as string but I can not.
Please help me. How to convert integer to binary, please tell me.
Input: 32
Output: 00100000
My code:
#include <stdio.h>
#include <string.h>
char converttobinary(int n)
{
int i;
int a[8];
char op;
for (i = 0; i < 8; i++)
{
a[i] = n % 2;
n = (n - a[i]) / 2;
}
for (i = 7; i >= 0; i--)
{
op = strcat(op, a[i]);
}
return op;
}
int main()
{
int n;
char str;
n = 254;
str = converttobinary(n);
printf("%c", str);
return 0;
}
I have tried to modify your solution with minimal changes to make it work. There are elegant solutions to convert Integer to Binary for example using shift operators.
One of the main issue in the code was you were using character instead of character array.
i.e char str; instead of char str[SIZE];
Also you were performing string operations on a single character. Additionally, iostream header file is for C++.
There is room for lot of improvements in the solution posted below (I only made your code work with minimal changes).
My suggestion is to make your C basics strong and approach this problem again.
#include <stdio.h>
#include <string.h>
void converttobinary(int n, char *op)
{
int i;
int a[8];
for (i = 0; i < 8; i++)
{
a[i] = n % 2;
n = (n - a[i]) / 2;
}
for (i = 7; i >= 0; i--)
{
op[i]=a[i];
}
}
int main()
{
int n,i;
char str[8];
n = 8;
converttobinary(n,str);
for (i = 7; i >= 0; i--)
{
printf(" %d ",str[i]);
}
return 0;
}
char *rev(char *str)
{
char *end = str + strlen(str) - 1;
char *saved = str;
while(end > str)
{
int tmp = *str;
*str++ = *end;
*end-- = tmp;
}
return saved;
}
char *tobin(char *buff, unsigned long long data)
{
char *saved = buff;
while(data)
{
*buff++ = (data & 1) + '0';
data >>= 1;
}
*buff = 0;
return rev(saved);
}
int main()
{
char x[128];
unsigned long long z = 0x103;
printf("%llu is 0b%s\n", z, tobin(x, z));
return 0;
}
I modify your code a little bit to make what you want,
the result of this code with
n = 10
is
00001010
In this code i shift the bits n positions of the imput and compare if there is 1 or 0 in this position and write a '1' if there is a 1 or a '0' if we have a 0.
#include <stdio.h>
void converttobinary(int n, char op[8]){
int auxiliar = n;
int i;
for (i = 0; i < 8; i++) {
auxiliar = auxiliar >> i;
if (auxiliar & 1 == 1){
op[7-i] = '1';
} else{
op[7-i] = '0';
}
auxiliar = n;
}
}
int main (void){
int n = 10;
int i;
char op[8];
converttobinary(n, op);
for(i = 7; i > -1; i--){
printf("%c",op[i]);
}
return 0;
}

char* giving different results when condition changes

I am creating a simple md5 bruteforce-like program using C. The only issue I am having is that the Found String: output completely changes if I were to replace a part of the if statement.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>
#include <time.h>
#include <stdbool.h>
#if defined(__APPLE__)
# define COMMON_DIGEST_FOR_OPENSSL
# include <CommonCrypto/CommonDigest.h>
# define SHA1 CC_SHA1
#else
# include <openssl/md5.h>
#endif
char *str2md5(const char *str, int length) {
int n;
MD5_CTX c;
unsigned char digest[16];
char *out = (char*)malloc(33);
MD5_Init(&c);
while (length > 0) {
if (length > 512) {
MD5_Update(&c, str, 512);
} else {
MD5_Update(&c, str, length);
}
length -= 512;
str += 512;
}
MD5_Final(digest, &c);
for (n = 0; n < 16; ++n) {
snprintf(&(out[n*2]), 16*2, "%02x", (unsigned int)digest[n]);
}
return out;
}
typedef struct md5data {
char* output;
char* strin;
} md5data;
md5data getrand() {
for (int i = 0; i < 10; ++i)
{
rand();
srand(rand());
}
unsigned char strin[50];
for (int i = 0; i < 50; i++)
{
strin[i] = (rand()%94)+32;
}
strin[49] = '\0';
char* string = &strin;
char *output = str2md5(string, strlen(string));
md5data out;
out.output = output;
out.strin = string;
return out;
}
bool starts_with(const char* a, const char* b)
{
if(strncmp(a, b, strlen(b)) == 0) return 1;
return 0;
}
int main() {
char input;
printf("%s","Enter Search String: ");
scanf("%s",&input);
srand(time(NULL));
while(1 == 1) {
md5data md5 = getrand();
if(starts_with(md5.output,&input)) {
printf("Found String: %s\nMD5: %s\n",md5.strin,md5.output);
break;
}
}
return 0;
}
Whenever I compile and execute, the first line of output is usually something like Found String: 0????
However, if I change starts_with(md5.output,&input) to something like 1==1 or anything like that, the output is something like Found String: qM39$dcX_ZqFM9]?>jKhxSl#m2xrAxaL*
What is causing the output to change and why is it happening?
The problem is on lines:
char input;
printf("%s","Enter Search String: ");
scanf("%s",&input);
input should be a char array (a buffer), and not a single char.
For example:
char input[256];
printf("%s","Enter Search String: ");
scanf("%s",&input);
In the current state, the scanf results in a buffer overflow on your stack, which causes undefined results.
I ended up fixing this issue by adding a global variable, removing md5data, and using strcpy to copy the value form getrand into the global variable.
Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>
#include <time.h>
#include <stdbool.h>
#if defined(__APPLE__)
# define COMMON_DIGEST_FOR_OPENSSL
# include <CommonCrypto/CommonDigest.h>
# define SHA1 CC_SHA1
#else
# include <openssl/md5.h>
#endif
char *str2md5(const char *str, int length) {
int n;
MD5_CTX c;
unsigned char digest[16];
char *out = (char*)malloc(33);
MD5_Init(&c);
while (length > 0) {
if (length > 512) {
MD5_Update(&c, str, 512);
} else {
MD5_Update(&c, str, length);
}
length -= 512;
str += 512;
}
MD5_Final(digest, &c);
for (n = 0; n < 16; ++n) {
snprintf(&(out[n*2]), 16*2, "%02x", (unsigned int)digest[n]);
}
return out;
}
unsigned char stringglobal[50];
char* outputglobal;
void getrand() {
for (int i = 0; i < 10; ++i)
{
rand();
srand(rand());
}
unsigned char strin[50] = {0};
for (int i = 0; i < 50; i++)
{
strin[i] = (rand()%94)+32;
}
strin[49] = '\0';
char* string = &strin[0];
char *output = str2md5(string, strlen(string));
outputglobal = output;
strcpy(stringglobal,string);
}
bool starts_with(const char* a, const char* b)
{
if(strncmp(a, b, strlen(b)) == 0) return 1;
return 0;
}
int main() {
char input[256];
printf("%s","Enter Search String: ");
scanf("%s",&input);
srand(time(NULL));
while(1 == 1) {
getrand();
if(starts_with(outputglobal,&input)) {
printf("Found! String: %s\nMD5: %s\n",stringglobal,outputglobal);
break;
}
}
return 0;
}

Converting lowercase letters to uppercase

I have a program to reverse a string and convert it to uppercase. If I write helloworld!, the output must be !DLROWOLLEH. But if I write hello world! the output is !DLRO. Could you tell me where the possible problem is?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
char * reverse(const char * text)
{
if (text==NULL)
return NULL;
int length = strlen(text);
char * reversed_string = malloc(length+1);
for(int i = 0; i < length/2; ++i)
{
reversed_string[i] = text[(length-1) - i];
reversed_string[(length-1) - i] = text[i];
}
reversed_string[length] = '\0';
//upper(reversed_string);
return reversed_string;
}
void upper(char *str1)
{
while(*str1!='\0')
{
if(*str1>96&&*str1<123)
*str1=*str1-32;
str1++;
}
}
int main(int argc, char * argv[])
{
char p[256];
fgets(p, sizeof(p), stdin);
char * rev_str = reverse(p);
upper(rev_str);
printf("%s\n", rev_str);
rev_str = 0;
return 0;
}
The problem is here
for(int i = 0; i < length/2; ++i)
It length is an odd number (like 11 in your example), this will implicitly round down, and as a consequence, you never write to the middle element in the string. Un your case, this happened to be 0, but that is not guaranteed to be so, so any character might have appeared there, instead of terminating the string early.
The easiest fix would be changing that to (length+1)/2, but that will have the effect that you write the middle element twice.
Actually, I think it is much easier if you just reverse the string just by iterating over it in one direction instead of from both.
I've modified your code and it works as expected.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
char * reverse(const char * text)
{
if (text==NULL)
return NULL;
unsigned long length = strlen(text);
char * reversed_string = malloc(length+1);
for(int i = 0; i < length; ++i)
{
reversed_string[i] = text[(length-1) - i];
//reversed_string[(length-1) - i] = text[i];
}
reversed_string[length] = '\0';
//upper(reversed_string);
return reversed_string;
}
void upper(char *str1)
{
while(*str1!='\0')
{
if(*str1>96&&*str1<123)
*str1=*str1-32;
str1++;
}
}
int main(int argc, char * argv[])
{
char p[256];
fgets(p, sizeof(p), stdin);
char * rev_str = reverse(p);
printf("%s\n", rev_str);
upper(rev_str);
printf("%s\n", rev_str);
rev_str = 0;
return 0;
}

Resources