LinuxQuestions.org
Latest LQ Deal: Latest LQ Deals
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 08-01-2019, 02:32 PM   #1
schneidz
LQ Guru
 
Registered: May 2005
Location: boston, usa
Distribution: fedora-35
Posts: 5,313

Rep: Reputation: 918Reputation: 918Reputation: 918Reputation: 918Reputation: 918Reputation: 918Reputation: 918Reputation: 918
[c] shift bytes in an array


hi, is there a smarter way to do this ?:
Code:
 c = fgetc(fstream);
 while(c != EOF)
 {
  carr[0] = carr[1]; carr[1] = carr[2]; carr[2] = carr[3]; carr[3] = carr[4]; carr[4] = carr[5]; carr[5] = carr[6]; carr[6] = carr[7]; carr[7] = carr[8]; carr[8] = c;
  printf("%c", carr[0]);
  if(strcmp(carr, "012345678") == 0)
   sprintf(carr, "hispanola");
}
 
Old 08-01-2019, 02:43 PM   #2
rtmistler
Moderator
 
Registered: Mar 2011
Location: USA
Distribution: MINT Debian, Angstrom, SUSE, Ubuntu, Debian
Posts: 9,883
Blog Entries: 13

Rep: Reputation: 4930Reputation: 4930Reputation: 4930Reputation: 4930Reputation: 4930Reputation: 4930Reputation: 4930Reputation: 4930Reputation: 4930Reputation: 4930Reputation: 4930
Without libraries? yes and no. Yes, you can use pointers, but no it's all manually moved byte by byte, just with a loop or something.

With libraries? memmove(3) - Recommend you read the manual page thoroughly. It DOES allow for overlapping regions, but one has to be careful about src/dst and that you're not obliterating src as you go along.

Edit: And the manual page says that it does move bytes into a temporary array, so if you're moving left to right (array-wise) then it won't do the obliteration thing I feared. I'd test that though. (Me being shifty-eyed and not trusting all library calls. )

Last edited by rtmistler; 08-01-2019 at 02:45 PM.
 
2 members found this post helpful.
Old 08-01-2019, 04:42 PM   #3
wainamoinen
Member
 
Registered: Sep 2009
Location: Belgium
Distribution: Slackware
Posts: 32

Rep: Reputation: 24
I'm not sure what you want to do exactly, but you can operate in groups of eight characters as an 64 bit integer, and do a right shift of 8 bits. NOTE that the right shift works on little endian architectures, on big endian architectures you would need to use a left shift.

So, on your example to shift a string of 9 characters plus '\0', the shift can be done as shown on the next code.

Code:
#include <stdio.h>
#include <stdint.h>

#define ORIGINAL  "abcdefghi"
#define CHARACTER 'x'

void Method1(void)
{
	char carr[10] = ORIGINAL;
	char c = CHARACTER;

	printf("\nMethod 1\n");
	printf("Original: %s\n", carr);
	carr[0] = carr[1]; carr[1] = carr[2]; carr[2] = carr[3]; carr[3] = carr[4]; carr[4] = carr[5]; carr[5] = carr[6]; carr[6] = carr[7]; carr[7] = carr[8]; carr[8] = c;
	printf("Shifted:  %s\n", carr);
}

void Method2(void)
{
	char carr[10] = ORIGINAL;
	char c = CHARACTER;

	printf("\nMethod 2\n");
	printf("Original: %s\n", carr);
	*(int64_t*)&carr >>= 8;
	carr[7] = carr[8];
	carr[8] = c;
	printf("Shifted:  %s\n", carr);
}

int main(void)
{
	Method1();
	Method2();

	return 0;
}
The result will be
Code:
gcc carr.c -Wall -Wextra -pedantic -o carr
./carr

Method 1
Original: abcdefghi
Shifted:  bcdefghix

Method 2
Original: abcdefghi
Shifted:  bcdefghix
If you want to use this method with larger strings, you will need to be sure that the buffer (carr) has a size of a multiple of 8 (plus the null terminator). And your code will be less clear and perhaps more difficult to maintain.
 
1 members found this post helpful.
Old 08-01-2019, 05:27 PM   #4
ntubski
Senior Member
 
Registered: Nov 2005
Distribution: Debian, Arch
Posts: 3,784

Rep: Reputation: 2083Reputation: 2083Reputation: 2083Reputation: 2083Reputation: 2083Reputation: 2083Reputation: 2083Reputation: 2083Reputation: 2083Reputation: 2083Reputation: 2083
Quote:
Originally Posted by schneidz View Post
hi, is there a smarter way to do this ?
If by "this" you just mean "shift bytes in an array", then I second rtmistler's suggestion of memmove. If the question is more about recognizing a string in a stream, then I would structure it like this:

Code:
  const char* findme = "012345678";
  const char* findme_end = findme + strlen(findme);
  const char* found = findme;

  while(c != EOF)
  {
    c = fgetc(fstream);
    if (c == *found)
      found++;
    else
      found = findme;
    if (found == findme_end)
    {
      printf("hispanola");
      found = findme;
    }
  }
For more sophisticated stuff, you could look at using a lexer or similar.

Quote:
Originally Posted by rtmistler View Post
Edit: And the manual page says that it does move bytes into a temporary array, so if you're moving left to right (array-wise) then it won't do the obliteration thing I feared. I'd test that though. (Me being shifty-eyed and not trusting all library calls. )
memcpy is the one which does not work with overlapping src/dst, memmove should be fine.
 
1 members found this post helpful.
Old 08-01-2019, 06:13 PM   #5
rtmistler
Moderator
 
Registered: Mar 2011
Location: USA
Distribution: MINT Debian, Angstrom, SUSE, Ubuntu, Debian
Posts: 9,883
Blog Entries: 13

Rep: Reputation: 4930Reputation: 4930Reputation: 4930Reputation: 4930Reputation: 4930Reputation: 4930Reputation: 4930Reputation: 4930Reputation: 4930Reputation: 4930Reputation: 4930
Quote:
Originally Posted by schneidz View Post
hi, is there a smarter way to do this ?:
Code:
 c = fgetc(fstream);
 while(c != EOF)
 {
  carr[0] = carr[1]; carr[1] = carr[2]; carr[2] = carr[3]; carr[3] = carr[4]; carr[4] = carr[5]; carr[5] = carr[6]; carr[6] = carr[7]; carr[7] = carr[8]; carr[8] = c;
  printf("%c", carr[0]);
  if(strcmp(carr, "012345678") == 0)
   sprintf(carr, "hispanola");
}
A second look by the way, because one thought to me originally was to use a pointer and move back one character, decide what to do with the new first character, and call it a day.

What's missing is a proper definition of the carr[] array, as well as a definition as to how this is tied, or not tied to the variable c.

If your intention is to rotate new characters into an array, we don't know.
 
Old 08-01-2019, 06:15 PM   #6
rtmistler
Moderator
 
Registered: Mar 2011
Location: USA
Distribution: MINT Debian, Angstrom, SUSE, Ubuntu, Debian
Posts: 9,883
Blog Entries: 13

Rep: Reputation: 4930Reputation: 4930Reputation: 4930Reputation: 4930Reputation: 4930Reputation: 4930Reputation: 4930Reputation: 4930Reputation: 4930Reputation: 4930Reputation: 4930
I mean I'd just fill the array in from the end, or second to last location, with each character and adjust the pointer backwards as it goes, and provide the pointer once it's all saved.

And, you know, overflow avoidance to not go beneath the zero element and set the last location to NULL so as to make it a string, ... verify if each input character is printable.

Last edited by rtmistler; 08-01-2019 at 06:18 PM.
 
Old 08-01-2019, 07:23 PM   #7
schneidz
LQ Guru
 
Registered: May 2005
Location: boston, usa
Distribution: fedora-35
Posts: 5,313

Original Poster
Rep: Reputation: 918Reputation: 918Reputation: 918Reputation: 918Reputation: 918Reputation: 918Reputation: 918Reputation: 918
Quote:
Originally Posted by rtmistler View Post
Without libraries? yes and no. Yes, you can use pointers, but no it's all manually moved byte by byte, just with a loop or something.

With libraries? memmove(3) - Recommend you read the manual page thoroughly. It DOES allow for overlapping regions, but one has to be careful about src/dst and that you're not obliterating src as you go along.

Edit: And the manual page says that it does move bytes into a temporary array, so if you're moving left to right (array-wise) then it won't do the obliteration thing I feared. I'd test that though. (Me being shifty-eyed and not trusting all library calls. )
big up. my searches kept pointing me to shift() but i think thats for shifting bits (instead of whole bytes).
 
Old 08-01-2019, 08:03 PM   #8
schneidz
LQ Guru
 
Registered: May 2005
Location: boston, usa
Distribution: fedora-35
Posts: 5,313

Original Poster
Rep: Reputation: 918Reputation: 918Reputation: 918Reputation: 918Reputation: 918Reputation: 918Reputation: 918Reputation: 918
Quote:
Originally Posted by rtmistler View Post
A second look by the way, because one thought to me originally was to use a pointer and move back one character, decide what to do with the new first character, and call it a day.

What's missing is a proper definition of the carr[] array, as well as a definition as to how this is tied, or not tied to the variable c.

If your intention is to rotate new characters into an array, we don't know.
thanx for rechecking. for your curiosity, i wanted to copy an mvs-mainframe dataset substituting about a dozen org-id's into proper values (the dataset is mostly ascii but has random binaries and ascii-10 (lf)'s thrown in).
so sed, awk, cut would choke on it. weirdly, head was able to read the whole line. also fgets(), getline() wasnt able to read the whole line either.
so i decided to process the file one byte at a time instead.
 
Old 08-02-2019, 05:03 AM   #9
ntubski
Senior Member
 
Registered: Nov 2005
Distribution: Debian, Arch
Posts: 3,784

Rep: Reputation: 2083Reputation: 2083Reputation: 2083Reputation: 2083Reputation: 2083Reputation: 2083Reputation: 2083Reputation: 2083Reputation: 2083Reputation: 2083Reputation: 2083
Quote:
Originally Posted by schneidz View Post
bmy searches kept pointing me to shift() but i think thats for shifting bits (instead of whole bytes).
I think shift() is perl: https://perldoc.perl.org/functions/shift.html

C has some bit shifting operators, but no function called "shift", as far as I know.


Quote:
Originally Posted by schneidz View Post
(the dataset is mostly ascii but has random binaries and ascii-10 (lf)'s thrown in).
so sed, awk, cut would choke on it.
Maybe they try and fail to decode as UTF-8? Setting LANG=C might help there.
 
1 members found this post helpful.
Old 08-02-2019, 06:11 AM   #10
schneidz
LQ Guru
 
Registered: May 2005
Location: boston, usa
Distribution: fedora-35
Posts: 5,313

Original Poster
Rep: Reputation: 918Reputation: 918Reputation: 918Reputation: 918Reputation: 918Reputation: 918Reputation: 918Reputation: 918
Quote:
Originally Posted by ntubski View Post
...
C has some bit shifting operators, but no function called "shift", as far as I know.
...
good correction.

for completions sake:[untested]
Code:
c = fgetc(fstream);
 while(c != EOF)
 {
  memmove(carr, carr+1, 8); carr[8] = c;
  printf("%c", carr[0]);
  if(strcmp(carr, "012345678") == 0)
   sprintf(carr, "hispanola");
}

Last edited by schneidz; 08-02-2019 at 06:22 AM.
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
gpg: do_plaintext(): wrote 1210414045 bytes but expected 822504068 bytes MensaWater Linux - Software 6 02-27-2018 08:48 AM
Linux CentOs shortcut remap Shift+4, Shift+6 lamakaha Linux - Newbie 4 05-12-2016 09:09 AM
Is it okay if my sector size is "512 bytes / 4096 bytes" Altiris Slackware 5 07-31-2015 03:19 AM
shift+End and Shift+Home key combo doesn't work right santana Linux - Hardware 6 04-23-2010 11:35 AM
TX bytes vs. httpd bytes ovrload Linux - Networking 3 10-12-2005 04:19 PM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 08:19 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration