I need to split a string and need to store in two seperate variables. The string contains a tab space. so it need to be seperated from the tab space
EG: the string looks like this
Sony <TAB> A Hindi channel.
I need to store Sony in one variable say char a[6]; and A Hindi Channel in another Variable say char b[20];
How can do this?
Tokenize string for a lot of programming language: link
In your case < tab > is a special character and it can be indicated as '\t'.
If you are using C programming language
#include<string.h>
#include<stdio.h>
#include<stdlib.h>
int main(void) {
char *a[5];
const char *s="Sony\tA Hindi channel.";
int n=0, nn;
char *ds=strdup(s);
a[n]=strtok(ds, "\t");
while(a[n] && n<4) a[++n]=strtok(NULL, "\t");
// a[n] holds each token separated with tab
free(ds);
return 0;
}
For C++ without using boost library:
#include <string>
#include <sstream>
#include <vector>
#include <iterator>
#include <iostream>
#include <algorithm>
int main() {
std::string s = "Sony\tA Hindi channel.";
std::vector<std::string> v;
std::istringstream buf(s);
for(std::string token; getline(buf, token, '\t'); )
v.push_back(token);
// elements of v vector holds each token
}
Using C++ and boost: How to tokenize a string in C++
#include <iostream>
#include <string>
#include <boost/foreach.hpp>
#include <boost/tokenizer.hpp>
using namespace std;
using namespace boost;
int main(int, char**) {
string text = "Sony\tA Hindi channel.";
char_separator<char> sep("\t");
tokenizer< char_separator<char> > tokens(text, sep);
BOOST_FOREACH (const string& t, tokens) {
cout << t << "." << endl;
}
}
Probably the strtok function is that you are looking
My C is old but something like that should work:
#include <stdio.h>
int getTabPosition (char str [])
{
int i = 0;
//While we didn t get out of the string
while (i < strlen(str))
{
//Check if we get TAB
if (str[i] == '\t')
//return it s position
return i;
i = i + 1;
}
//If we get out of the string, return the error
return -1;
}
int main () {
int n = 0;
//Source
char str [50] = "";
//First string of the output
char out1 [50] = "";
//Second string of the output
char out2 [50] = "";
scanf(str, "%s");
n = getTabPosition(str);
if (n == -1)
return -1;
//Copy the first part of the string
strncpy(str, out1, n);
//Copy from the end of out1 in str to the end of str
//str[n + 1] to skip the tab
memcpy(str[n+1], out2, strlen(str) - n);
fprintf(stdout, "Original: %s\nout1=%s\nout2=%s", str, out1, out2);
return 0;
}
Untested, but the principe is there
Related
This is my code:
#include <stdio.h>
#include <string.h>
#define VERSION "2.16.0.0"
int main ()
{
//char buf[] ="2.16.0.0";
int i = 0;
int j ;
char letter[8];
//char a[] = VERSION;
for(i=0;i<8;i++)
{
letter[i] = VERSION[i];
}
char *array;
char* copy = letter ;
while ((array = strtok_r(copy, ".", ©)))
printf("%s\n", array);
printf("%s", array);
}
I split the macro to 2 16 0 0.
Now, I want to format it to 02 16 00 00. How do I do it?
I tried using sprintf() function to format the array but that didn't work out, any other way?
Your program can be simplified in several ways (see below) and I have to point out at least one significant error since the copy of the string in letter does not include the terminating 0.
About how to print, as I understand you would like to print the numerical entries with 2 digits. One method to do that is to convert them to integers and format the output using the printf formatting options:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define VERSION "2.16.0.0"
int main ()
{
char *element;
char copy[] = VERSION;
element = strtok(copy, ".");
while (element != NULL)
{
printf("%02d ", atoi(element));
element = strtok(NULL, ".");
}
}
i have this data
27a1bc
thats supposed to be a data recieved from serial communication/uart.
the question is, is there anyway i could separate this data without delimeter? i need the data change to this
27
a1
bc
is there anyway i could do this without delimeter/strtok?
here is my code, im stuck.
#include <stdio.h>
#include <stdlib.h>
char usart[] = "27a1bc";
int main(void) {
// your code goes here
scanf("%c", usart[1]);
scanf("%c", usart[0]);
return 0; }
You can use a pointer to an array of 3 char's (2 + 1 for the trailing NUL) and memcpy in a loop:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char usart[] = "27a1bc";
int main(void)
{
size_t i, n = sizeof usart / 2;
char (*token)[3];
token = calloc(n, sizeof *token);
if (token == NULL) {
perror("calloc");
exit(EXIT_FAILURE);
}
for (i = 0; i < n; i++) {
memcpy(token[i], usart + (i * 2), 2);
puts(token[i]);
}
free(token);
return 0;
}
My code is suppose to initialise any word you type but it is refusing to compile
.
I don't understand the error messages it is giving to me.
1 initialize.c:24:23: error: incompatible integer to pointer conversion passing 'char' to parameter of type 'const char *'; take the
address with & [-Werror,-Wint-conversion]
2 initialize.c:21:23: error: format string is not a string literal (potentially insecure) [-Werror,-Wformat-security]
3 initialize.c:21:23: error: format string is not a string literal (potentially insecure) [-Werror,-Wformat-security]
printf(toupper(s[i]));
#include <stdio.h>
#include<cs50.h>
#include<string.h>
#include<ctype.h>
void initialize(string s);
int main(int argc, string argv[])
{
printf("May I have your name?");
string name = GetString();
initialize(name);
}
void initialize(string s)
{
int space = 1;
for (int i = 0;i < strlen(s); i++)
{ if(space == 1)
{
printf(toupper(s[i]));
space -= 1;
}
if(strncmp(s[i]," ",1 ) )
{
space += 1;
}
}
}
printf expects a format string with type const char* as its 1st argument, so:
change
printf(toupper(s[i]));
to
printf("%c", toupper(s[i]));
And as #Matt McNabb pointed, strncmp has the similar problem here. Because you tend to compare the 1st char only, you chould change
if(strncmp(s[i]," ",1 ) )
to
if (s[i] == ' ')
to make it clearer and more effective.
here is the code, after making it portable
But not handling user input errors
It has the necessary corrections so it cleanly compiles
#include <stdio.h>
#include <stdlib.h>
//#include <cs50.h>
#include <string.h>
#include <ctype.h>
void initialize(char * s);
int main( void )
{
printf("May I have your name?");
char name[50] = {'\0'};
fgets(name, sizeof(name), stdin ); // should check returned value
// to assure the line input was successful
initialize(name);
return 0;
} // end function: main
void initialize(char * s)
{
int space = 1;
for (size_t i = 0;i < strlen(s); i++)
{
if(space == 1)
{
printf("%c", toupper(s[i]));
space -= 1;
}
if( ' ' == s[i] ) // always place literal on left so compiler
// catches any place where '=' was used
// when it should have been '=='
{
space += 1;
}
}
} // end function: initialize
I'm trying to be able to decode encoded strings that were encoded using a perl script. The reason I can't just change the perl script is because a lot of important data already exists that was saved via the perl script and it would be too much to decode in perl and recode another way. It's easier just to keep things in place (for now). However, the compiled perl code is 2MB. I want to write it in C so the executable will be a smaller size.
What I have so far is below. It won't work though. It basically gives me junk output. The problem I think is that the perl script used a hex-based encryption. How do I go about decoding that? Can someone point me to where I went wrong?
/*
Test to decode perl-encrypted string.
NOTE: Not all code written by me. Function code is either written by or derived
from code from other people in response to similar questions found on the
internet.
Required Lib: crypt (-lcrypt)
Perl Code from existing script (that is being converted to C):
use Crypt::CBC;
use Crypt::DES;
my $text = "thisisalongtest";
my $salt_key = "fOagmJOKu2SF";
my $cipher = Crypt::CBC->new( -key => $salt_key, -cipher => 'DES' -header => 'none');
my $enc_text = $cipher->encrypt_hex($text);
Perl crypt functions require libcrypt-cbc-perl & libcrypt-des-perl
Data:
Original Text: thisisalongtest
Salt Key: fOagmJOKu2SF
Resulting Encrypted String: 53616c7465645f5f167ebac84042fe7ceac836e1d3e7d3aa1dfc27e0e8cad0f1
Resulting output:
Decrypted: (unprintable junk characters)
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <rpc/des_crypt.h>
#define BUFFSIZE 420
int encrypt(char key[9], char salt[9], char pass[BUFFSIZE], int mode);
void enc_from_hex(const char* st, char ret_result[BUFFSIZE]);
int hex_to_int(char c);
int hex_to_ascii(char c, char d);
int main (int argc, char *argv[]) {
int err;
char passwd[BUFFSIZE];
char result[BUFFSIZE];
char key[13];
sprintf(key,"fOagmJOKu2SF");
/* Change this from hex pairs to ASCII */
sprintf(passwd, "53616c7465645f5f167ebac84042fe7ceac836e1d3e7d3aa1dfc27e0e8cad0f1");
enc_from_hex(passwd, result);
/* Decrypt */
err = encrypt(key, "", result, 1); /* DO NOT use 'NULL' for 2nd parameter! */
if(err != 0) {
printf("Error.\n");
} else {
printf("Decrypted: %s\n", result);
}
return 0;
}
/* Encryption */
int encrypt(char key[13], char salt[13], char pass[BUFFSIZE], int mode){
char temp[13];
strcpy(temp, salt);
int buffsize;
int errcode;
des_setparity(key);
buffsize = strlen(pass);
/* Pad pass to ensure size is divisable by 8.*/
while (buffsize % 8 && buffsize<BUFFSIZE) {
pass[buffsize++] = '\0';
}
/* Determine Function */
if(mode == 1) {
errcode = cbc_crypt(key, pass, buffsize, DES_DECRYPT | DES_SW, temp);
} else {
errcode = cbc_crypt(key, pass, buffsize, DES_ENCRYPT | DES_SW, temp);
}
if (DES_FAILED(errcode) || strcmp(pass, "") == 0) {
return errcode;
}
return errcode;
}
/* Hex conversion functions */
void enc_from_hex(const char* st, char ret_result[BUFFSIZE]) {
char temp[2];
int length = strlen(st);
int i;
char buf = 0;
for(i = 0; i < length; i++) {
if(i % 2 != 0) {
sprintf(temp, "%c", hex_to_ascii(buf, st[i]));
strcat(ret_result, temp);
} else {
buf = st[i];
}
}
}
int hex_to_int(char c) {
int first = c / 16 - 3;
int second = c % 16;
int result = first*10 + second;
if(result > 9) result--;
return result;
}
int hex_to_ascii(char c, char d) {
int high = hex_to_int(c) * 16;
int low = hex_to_int(d);
return high+low;
}
As #ikegami points out in the comments the value passed to key Crypt::CBC is not really a key. This value is passed to another function which combines it with a random salt then hashes it to generate the real key and initialization vector. The random salt is saved with the cypher text the idea being if you encrypt the same data with the same key more than once the output will be different every time.
If you convert your encrypted string to ascii you will notice the first eight characters spell Salted__, this corresponds to the format used by OpenSSL.
See below for a somewhat crude example using OpenSSL's EVP api:
//
// compile with: gcc -o crypt crypt.c -lssl -lcrypto
//
#include <stdio.h>
#include <string.h>
#include <openssl/evp.h>
int main(int argc, char *argv[]){
char pass[]="fOagmJOKu2SF";
char text[]="53616c7465645f5f167ebac84042fe7ceac836e1d3e7d3aa1dfc27e0e8cad0f1";
int i = 0;
char *pos=text;
while(*pos){ // converts hex string to binary in place
sscanf(pos, "%2hhx", &text[i++]);
pos += 2;
} text[i]=0;
EVP_CIPHER_CTX ctx;
unsigned char key[8] = {0};
unsigned char iv[8] = {0};
int len;
char *clear = malloc(strlen(text));
// v-> First Charicter after 'Salted__'
EVP_BytesToKey(EVP_des_cbc(), EVP_md5(), &text[8], pass, strlen(pass), 1, key, iv);
EVP_DecryptInit(&ctx, EVP_des_cbc(), key, iv);
// v-> Cypertext starts after salt
EVP_DecryptUpdate(&ctx, clear, &len, &text[16], strlen(text)-15);
EVP_DecryptFinal(&ctx, clear, &len);
printf("%s\n", clear);
return 0;
}
http://www.ict.griffith.edu.au/anthony/info/crypto/openssl.hints
https://www.openssl.org/docs/manmaster/crypto/EVP_BytesToKey.html
https://www.openssl.org/docs/manmaster/crypto/EVP_EncryptInit.html
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.