#include<stdio.h>
#define msize 4096
struct memory
{
int a[msize];
};
void read(struct memory *m)
{
int i;
for(i=0;i<sizeof(msize);i++)
{
scanf("%d",&m->a[i]);
}
}
int main()
{
struct memory m;
m.a[0]=250; // temperature value of 25,0
m.a[4]=01; // heater status OFF
m.a[8]=240; // temperature value of 24,0
m.a[12]=00; // heater status ON
m.a[16]=220; // temperature value of 22,0
m.a[20]=00; // heater status ON
read(&m);
return 0;
}
I have created a structure of a particular memory size and inserted some values to the array and reading those values from the array. I have a difficulty to convert this value to ASCII.
In for(i=0;i<sizeof(msize);i++), it will not be i<4096,rather it will compare i to the size of an integer on your platform.In 32-bit systems,it will be 4.So the loop will exit after just 4 iterations.
Further in your function, &m->a[i] will be m->a[i] as m is a pointer.
PS There is something very wrong with the logic of your program.You are assigning some values to the array elements in main(),but are overwriting the same in the function read().
As for converting integer values from an array to ASCII, it's fairly simple.You just have to use the %c format specifier and pass the array elements are arguments.But I must point out there aren't 450 ASCII values to print.Since a character only has one byte,the max you can manage with it is 256 characters.
PS Many of the ASCII characters you want to print are not print-able.One is whose ASCII value equals 0.
My suggestion is inputting by character if you want to store in ASCII.
like this
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#define msize 4096
struct memory {
char a[msize];
};
/*
m.a[0]=250; // temperature value of 25,0
m.a[4]=01; // heater status OFF
m.a[8]=240; // temperature value of 24,0
m.a[12]=00; // heater status ON
m.a[16]=220;// temperature value of 22,0
m.a[20]=00; // heater status ON
*/
int read(struct memory *m){
char inputbuff[4+1];
int i=0;
memset(m->a, ' ', sizeof(m->a)/sizeof(m->a[0]));//initialize by space
while(i<msize/(4+4)){
printf("input temperature value e.g.25,0 : 250(and enter)\n");
fgets(inputbuff, sizeof(inputbuff), stdin);
strncpy(m->a + i*4, inputbuff, 3);
//i+=1;
printf("input heater status ON or OFF e.g.ON : 00 , OFF : 01(and enter)\n");
fgets(inputbuff, sizeof(inputbuff), stdin);
strncpy(m->a + (i+1)*4, inputbuff, 2);
i += 1;
printf("continue input? (y or n) : ");
fgets(inputbuff, sizeof(inputbuff), stdin);
if(*inputbuff=='n' || *inputbuff=='N'){
break;
}
}
return i;
}
int main(void){
struct memory m;
read(&m);
{
//check print
m.a[msize-1]='\0';
printf("%s\n", m.a);
}
return 0;
}
ADD for more
#include <stdio.h>
#include <string.h>
#define msize 4098
int *storeInt(void *address){
int *ip =(int*)address;
*ip = 777;//ip[0]=777;ip[1]=888;...
return ip;
}
char *storeChars(void *address){
char *cp =(char*)address;
strcpy(cp, "hello");
return cp;
}
void dump(void *address, size_t length){
unsigned char *cp = (unsigned char*)address;
size_t i;
for(i=0;i<length;++i){
if(i % 16 == 0) printf("\n");
printf("%02X ", *cp++);
}
}
int main(void){
static char memory[msize];//create a static memory of a particular size
char *block1, *block2;
block1 = &memory[0];
block2 = &memory[1024*2];//split a virtual
int *ip;
ip=storeInt(block1);//store some values in the memory
printf("%d\n", *ip);//read the values from the memory
char *cp;
cp=storeChars(block2);//set hello\0
printf("%s\n", cp);//say hello
char ascValue[12];
int value = *ip;//777
//convert "value of int" to Ascii
sprintf(ascValue, "%d", value);
//Display it
printf("value is %s\n", ascValue);
dump(block1, 8);
dump(block2, 8);
return 0;
}
If your read() function is intended to read from memory and print to a terminal then you should be using printf() instead of scanf(). printf() will convert integer values to ASCII through the %d format string. scanf() reads from the standard input and stores to memory. scanf() converts from ASCII to integer through the %d format string.
Related
Hello I have variable like this:
uint8_t *str value = "100663296";
I just wan't to convert to hexadecimal interpretation of str.
I doesn't need any math operations on this variable.
uint8_t *output value = "6000000";
How to do it correctly? I can't use convert to int and use sprintf because i don't have memmory for this on my MCU.
UPDATE: missed the part about MCU and memory limitations :) this answer won't be useful
You can try to do the following:
convert your string representation of the number to integer value (you can use int atoi( const char * str ); function
once you have your integer you can print it as HEX using, for example, sprintf function with %x as a format parameter and you integer as a value parameter
Here is a working example: https://ideone.com/axAPWH
#include <iostream>
using namespace std;
int main() {
int n;
char hex_val[50];
n = atoi("100663296");
sprintf(hex_val, "%x", n);
cout << hex_val;
return 0;
}
Could use <charconv> if available:
#include <charconv>
#include <cstdio>
#include <cstdlib>
int main() {
auto const* str = "2147483647";
errno = 0;
char* end;
long i = std::strtol(str, &end, 10);
if (end == str || errno == ERANGE)
return 1;
char out[20];
auto const [p, err] = std::to_chars(out, out + sizeof out, i, 16);
if (err != std::errc{})
return 2;
*p = 0; // null terminate
std::puts(out);
}
I am trying to convert some C++ code to C for my compiler that can't run with C++ code. I'd like to create the template below to C. This template converts the decimal integer to hexadecimal, and adds 0 in front of value if the size of the hexadecimal string is smaller than (sizeof(T)*2). Data type T can be unsigned char, char, short, unsigned short, int, unsigned int, long long, and unsigned long long.
template< typename T > std::string hexify(T i)
{
std::stringbuf buf;
std::ostream os(&buf);
os << std::setfill('0') << std::setw(sizeof(T) * 2)
<< std::hex << i;
std::cout<<"sizeof(T) * 2 = "<<sizeof(T) * 2<<" buf.str() = "<<buf.str()<<" buf.str.c_str() = "<<buf.str().c_str()<<std::endl;
return buf.str().c_str();
}
Thank you for tour help.
Edit 1: I have tried to use the declaration
char * hexify (void data, size_t data_size)
but when I call with the int value int_value:
char * result = hexify(int_value, sizeof(int))
it doesn't work because of:
noncompetitive type (void and int).
So in this case, do I have to use a macro? I haven't tried with macro because it's complicated.
C does not have templates. One solution is to pass the maximum width integer supported (uintmax_t, in Value below) and the size of the original integer (in Size). One routine can use the size to determine the number of digits to print. Another complication is C does not provide C++’s std::string with is automatic memory management. A typical way to handle this in C is for the called function to allocate a buffer and return it to the caller, who is responsible for freeing it when done.
The code below shows a hexify function that does this, and it also shows a Hexify macro that takes a single parameter and passes both its size and its value to the hexify function.
Note that, in C, character constants such as 'A' have type int, not char, so some care is needed in providing the desired size. The code below includes an example for that.
#include <inttypes.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
char *hexify(size_t Size, uintmax_t Value)
{
// Allocate space for "0x", 2*Size digits, and a null character.
size_t BufferSize = 2 + 2*Size + 1;
char *Buffer = malloc(BufferSize);
// Ensure a buffer was allocated.
if (!Buffer)
{
fprintf(stderr,
"Error, unable to allocate buffer of %zu bytes in %s.\n",
BufferSize, __func__);
exit(EXIT_FAILURE);
}
// Format the value as "0x" followed by 2*Size hexadecimal digits.
snprintf(Buffer, BufferSize, "0x%0*" PRIxMAX, (int) (2*Size), Value);
return Buffer;
}
/* Provide a macro that passes both the size and the value of its parameter
to the hexify function.
*/
#define Hexify(x) (hexify(sizeof (x), (x)))
int main(void)
{
char *Buffer;
/* Show two examples of using the hexify function with different integer
types. (The examples assume ASCII.)
*/
char x = 'A';
Buffer = hexify(sizeof x, x);
printf("Character '%c' = %s.\n", x, Buffer); // Prints "0x41".
free(Buffer);
int i = 123;
Buffer = hexify(sizeof i, i);
printf("Integer %d = %s.\n", i, Buffer); // Prints "0x00007b".
free(Buffer);
/* Show examples of using the Hexify macro, demonstrating that 'A' is an
int value, not a char value, so it would need to be cast if a char is
desired.
*/
Buffer = Hexify('A');
printf("Character '%c' = %s.\n", 'A', Buffer); // Prints "0x00000041".
free(Buffer);
Buffer = Hexify((char) 'A');
printf("Character '%c' = %s.\n", 'A', Buffer); // Prints "0x41".
free(Buffer);
}
You don't need templates if you step down to raw bits and bytes.
If performance is important, it is also best to roll out the conversion routine by hand, since the string handling functions in C and C++ come with lots of slow overhead. The somewhat well-optimized version would look something like this:
char* hexify_data (char*restrict dst, const char*restrict src, size_t size)
{
const char NIBBLE_LOOKUP[0xF+1] = "0123456789ABCDEF";
char* d = dst;
for(size_t i=0; i<size; i++)
{
size_t byte = size - i - 1; // assuming little endian
*d = NIBBLE_LOOKUP[ (src[byte]&0xF0u)>>4 ];
d++;
*d = NIBBLE_LOOKUP[ (src[byte]&0x0Fu)>>0 ];
d++;
}
*d = '\0';
return dst;
}
This breaks down any passed type byte-by-byte, using a character type. Which is fine, when using character types specifically. It also uses caller allocation for maximum performance. (It can also be made endianess-independent with an extra check per loop.)
We can make the call a bit more convenient with a wrapper macro:
#define hexify(buf, var) hexify_data(buf, (char*)&var, sizeof(var))
Full example:
#include <string.h>
#include <stdint.h>
#include <stdio.h>
#define hexify(buf, var) hexify_data(buf, (char*)&var, sizeof(var))
char* hexify_data (char*restrict dst, const char*restrict src, size_t size)
{
const char NIBBLE_LOOKUP[0xF+1] = "0123456789ABCDEF";
char* d = dst;
for(size_t i=0; i<size; i++)
{
size_t byte = size - i - 1; // assuming little endian
*d = NIBBLE_LOOKUP[ (src[byte]&0xF0u)>>4 ];
d++;
*d = NIBBLE_LOOKUP[ (src[byte]&0x0Fu)>>0 ];
d++;
}
*d = '\0';
return dst;
}
int main (void)
{
char buf[50];
int32_t i32a = 0xABCD;
puts(hexify(buf, i32a));
int32_t i32b = 0xAAAABBBB;
puts(hexify(buf, i32b));
char c = 5;
puts(hexify(buf, c));
uint8_t u8 = 100;
puts(hexify(buf, u8));
}
Output:
0000ABCD
AAAABBBB
05
64
an optional solution is to use format string like printf
note that you can't return pointer to local variable, but you can get the buffer as argument, (here it is without boundaries check).
char* hexify(char* result, const char* format, void* arg)
{
int size = 0;
if(0 == strcmp(format,"%d") || 0 == strcmp(format,"%u"))
{
size=4;
sprintf(result,"%08x",arg);
}
else if(0 == strcmp(format,"%hd") || 0 == strcmp(format,"%hu"))
{
size=2;
sprintf(result,"%04x",arg);
}
else if(0 == strcmp(format,"%hhd")|| 0 == strcmp(format,"%hhu"))
{
size=1;
sprintf(result,"%02x",arg);
}
else if(0 == strcmp(format,"%lld") || 0 == strcmp(format,"%llu") )
{
size=8;
sprintf(result,"%016x",arg);
}
//printf("size=%d", size);
return result;
}
int main()
{
char result[256];
printf("%s", hexify(result,"%hhu", 1));
return 0;
}
I am reading in a text file with lines of the format:
date =20170422,line =10,index =3,field =partType,lock =productCode1,bookmark=2/19/56,
I need to extract the name of the field (date, line, index, etc.) and its corresponding value into char field[] and char value[] variables. If necessary, I am allowed to modify the format of the lines.
My initial thinking was to use while loops and check for = and , characters but it was getting messy and it seems like there may be a cleaner way.
You could do something like the below example. Split the string by commas using getline from your file, then split use an istringstream to and getline to split it again by an equals sign.
#include<iostream>
#include<fstream>
#include<string>
#include<sstream>
int main()
{
std::ifstream file("test.txt");
std::string wholeLine, partOfLine;
while(std::getline(file, wholeLine, ',')) {
std::istringstream wholeLineSS(wholeLine);
while(std::getline(wholeLineSS, partOfLine, '=')) {
std::cout<<partOfLine<<std::endl;
}
}
return 0;
}
The program I post here extracts the parameters from one or more strings which are formatted as you require. The function extract extracts all the parameters contained in a string (of the format you specified) and insert their names and values in a structure (struct sParms) array.
You may compile the program as extract and execute it at the system prompt as:
username: ./extract "date =20170422,line =10,index =3,field
=partType,lock =productCode1,bookmark=2/19/56,"
The output will be the following:
[date]=[20170422]
[line]=[10]
[index]=[3]
[field]=[partType]
[lock]=[productCode1]
[bookmark]=[2/19/56]
You may execute the program with more than one string:
username: ./extract "date =20170422,line =10,index =3,field
=partType,lock =productCode1,bookmark=2/19/56," "yes=1, no=0"
The output will be the following:
[date]=[20170422]
[line]=[10]
[index]=[3]
[field]=[partType]
[lock]=[productCode1]
[bookmark]=[2/19/56]
[yes]=[1]
[no]=[0]
In the following line there's the code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <libgen.h>
//Parameters: date =20170422,line =10,index =3,field =partType,lock =productCode1,bookmark=2/19/56,
#define SEPARATOR ','
#define ASSIGNEMENT '='
typedef struct sParms {
char * fieldName;
char * fieldValue;
} tsParms;
int loadString(char *to, const char *from);
int extract(tsParms **oparms, const char *inb);
// Retrieve buffer length
int loadString(char *to, const char *from)
{
int len=0;
while(*from<=32 && *from!=SEPARATOR && *from!=ASSIGNEMENT)
from++;
// Get the string value
while(*from>32 && *from!=SEPARATOR && *from!=ASSIGNEMENT) {
*(to+len++)=*from;
++from;
}
*(to+len++)=0;
return len;
}
int extract(tsParms ** oparms, const char *inb)
{
int cnt=0,j;
const char * end, *equ, *start;
char * buff;
tsParms * parms;
if (inb == NULL || strlen(inb) == 0 || oparms == NULL)
return 0;
// It counts the number of parms
end=strchr(inb,ASSIGNEMENT);
while(end) {
cnt++;
end=strchr(end+1,ASSIGNEMENT);
}
if (!cnt)
return 0;
/* Doing some considerations we may assume that the memory to use to store
* fields name and values is the same of the input string (inb)
*
* The space to store the pointers is cnt * sizeof(tsParms *).
*/
j=cnt * sizeof(tsParms) + strlen(inb);
parms = malloc(j+1);
memset(parms,0,j+1);
buff = (char *)(parms+cnt); // The memory area where we can save data!
start=inb;end=start;cnt=0;
do {
end=strchr(start,SEPARATOR);
equ=strchr(start,ASSIGNEMENT);
if (equ) {
//Get the field name
parms[cnt].fieldName=buff;
buff+=loadString(buff,start);
//Get the field value
start=equ+1;
parms[cnt].fieldValue=buff;
buff+=loadString(buff,start);
cnt++;
}
if (end)
start=end+1;
} while(end);
*oparms = parms;
return cnt;
}
int main(int argc, char *argv[])
{
int i,j,cnt=0,retval=0;
tsParms * parms=NULL;
if (argc<2) {
printf("Usage: %s \"string-1\" [\"string-2\" ...\"string-n\"]\n",basename(argv[0]));
return 1;
}
for(i=1; i<argc; i++) {
cnt=extract(&parms, argv[i]);
if (cnt!=0 && parms!=NULL) {
for(j=0;j<cnt;j++) {
printf("[%s]=[%s]\n",parms[j].fieldName,parms[j].fieldValue);
}
puts("");
free((void *)parms);
} else {
retval=1;
break;
}
}
return retval;
}
I have a program, that asks several strings and should sort them.
My code is:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define MAX_STR_LEN 256
int myStrCmp (const void * a, const void * b)
{
return strcmp((const char *)a, (const char *)b);
}
int main(void)
{
int strNum; // expected number of input strings
int strCnt; // counter of strings
char ** storage; // pointr to the memory when strings are stored
char strBuf[ MAX_STR_LEN]; // buffer for strings
char * strPtr;
// input of strings number
do{
printf("How many strings will be entered: ");
while( scanf("%d", &strNum) != 1)
{
printf("ERROR: Not number was entered!\n");
while( getchar() != '\n' );
printf("Please enter a number: ");
}
if( strNum < 2 )
{
printf("ERROR: Number less than 2 was entered!\n");
}
while( getchar() != '\n' );
}
while(strNum < 2);
// allocation of memory for pointers
storage = (char **) calloc(strNum, sizeof(char*) );
if( storage == NULL )
{
printf("ERROR: Unexpected problems with memory allocation!\n");
return 1;
}
// input of strings
for( strCnt = 0; strCnt < strNum; strCnt++)
{
printf("Enter string #%d:\n", strCnt + 1);
fgets(strBuf, MAX_STR_LEN, stdin);
strPtr = strchr(strBuf, '\n');
if( strPtr )
{
*strPtr = '\0';
}
else
{
strBuf[ MAX_STR_LEN - 1] = '\0';
}
// allocation memory for particular string
storage[strCnt] = (char *) malloc(strlen(strBuf) + 1);
if(storage[strCnt] == NULL)
{
printf("ERROR: Unexpected problems with memory allocation!\n");
return 2;
}
// move string to dynamic memory
strcpy(storage[strCnt], strBuf);
}
// sort the strings
qsort(storage, strNum, sizeof(char**), myStrCmp);
// output the result
printf("\nSorted strings:\n");
for( strCnt = 0; strCnt < strNum; strCnt++)
{
printf("%s\n", storage[strCnt]);
}
return 0;
}
The simplest test shows the trouble:
How many strings will be entered: 3
Enter string #1:
ddd
Enter string #2:
aaa
Enter string #3:
ccc
Sorted strings:
ddd
aaa
ccc
I have tryed Visual C++ and gcc, but the result is the same. Please, say me what is wrong in the code?
The problem is in myStrCmp function.
Because a and b are elements in not a simple array, but in array of pointers, their type must be char ** and function that compares two elements have to be as follows:
int myStrCmp (const void * a, const void * b)
{
return strcmp(*(const char **)a, *(const char **)b);
}
I wrote this code to reverse strings. It works well, but when I enter short strings like "american beauty," it actually prints "ytuaeb nacirema2." This is my code. I would like to know what is wrong with my code that prints a random 2 at the end of the string. Thanks
// This program prompts the user to enter a string and displays it backwards.
#include <iostream>
#include <cstdlib>
using namespace std;
void printBackwards(char *strPtr); // Function prototype
int main() {
const int SIZE = 50;
char userString[SIZE];
char *strPtr;
cout << "Please enter a string (up to 49 characters)";
cin.getline(userString, SIZE);
printBackwards(userString);
}
//**************************************************************
// Definition of printBackwards. This function receives a *
// pointer to character and inverts the order of the characters*
// within it. *
//**************************************************************
void printBackwards(char *strPtr) {
const int SIZE = 50;
int length = 0;
char stringInverted[SIZE];
int count = 0;
char *strPtr1 = 0;
int stringSize;
int i = 0;
int sum = 0;
while (*strPtr != '\0') {
strPtr++; // Set the pointer at the end of the string.
sum++; // Add to sum.
}
strPtr--;
// Save the contents of strPtr on stringInverted on inverted order
while (count < sum) {
stringInverted[count] = *strPtr;
strPtr--;
count++;
}
// Add '\0' at the end of stringSize
stringInverted[count] == '\0';
cout << stringInverted << endl;
}
Thanks.
Your null termination is wrong. You're using == instead of =. You need to change:
stringInverted[count] == '\0';
into
stringInverted[count] = '\0';
// Add '\0' at the end of stringSize
stringInverted[count] == '\0';
Should use = here.
What is wrong with your code is that you do not even use strlen for counting the length of the string and you use fixed size strings (no malloc, or, gasp new[]), or the std::string (this is C++)! Even in plain C, not using strlen is always wrong because it is hand-optimized for the processor. What is worst, you have allocated the string to be returned (stringInverted) from the stack frame, which means when the function exits, the pointer is invalid and any time the code "works" is purely accidental.
To reverse a string on c++ you do this:
#include <iostream>
#include <string>
int main() {
std::string s = "asdfasdf";
std::string reversed (s.rbegin(), s.rend());
std::cout << reversed << std::endl;
}
To reverse a string in C99 you do this:
char *reverse(const char *string) {
int length = strlen(string);
char *rv = (char*)malloc(length + 1);
char *end = rv + length;
*end-- = 0;
for ( ; end >= rv; end --, string ++) {
*end = *string;
}
return rv;
}
and remember to free the returned pointer after use. All other answers so far are blatantly wrong :)