用C语言找出数组中二进制元素的第一位1

用C语言找出一个数组中第一个含有1的元素,且找出这个元素二进制的第几位是第一个1,从最低位开始。比如说第一个元素是10010000,那么就是找到它的第5位是第一个1

基于Monster 组和GPT的调写:
可以使用位运算来解决这个问题。首先,遍历整个数组,找到第一个含有1的元素,然后使用位运算操作找到它的第一个1的位置。

C实现代码:

#include <stdio.h>

int main() {
    int arr[] = {0b10010000, 0b01000000, 0b00000000, 0b11001000};
    int len = sizeof(arr) / sizeof(int);
    int first_one_element = -1;
    int first_one_position = -1;

    for (int i = 0; i < len; i++) {
        if ((arr[i] & 1) == 1) {
            // 找到第一个含有1的元素
            first_one_element = arr[i];

            // 找到第一个1的位置
            for (int j = 0; j < 32; j++) {
                if ((first_one_element >> j) & 1) {
                    first_one_position = j + 1;
                    break;
                }
            }

            break;
        }
    }

    printf("第一个含有1的元素是 %d,它的第一个1出现在第 %d 位\n", first_one_element, first_one_position);

    return 0;
}


在这个代码中,首先定义了一个包含一些测试数据的整型数组。然后使用循环遍历整个数组,当找到第一个含有1的元素时,就使用位运算找到第一个1的位置。最后,输出找到的结果。
这里假设一个整型变量占用32位

方法比较多吧。你的输入是一个整数,还是已经是二进制数字组成的数组了啊?说一下你觉得为难的地方,不然不清楚给你出什么点子


#include <stdio.h>

int find_first_one(int arr[], int n)
{
    int i, j, bit;

    for (i = 0; i < n; i++) {
        if (arr[i] != 0) {
            // 找到第一个非零元素
            bit = 1;
            for (j = 0; j < sizeof(int) * 8; j++) {
                if ((arr[i] & bit) != 0) {
                    // 找到第一个为1的位
                    return i * sizeof(int) * 8 + j + 1;
                }
                bit <<= 1;
            }
        }
    }

    return -1;
}

int main()
{
    int arr[] = {0x0000, 0x0000, 0x0000, 0x9010};
    int index = find_first_one(arr, sizeof(arr) / sizeof(int));

    if (index != -1) {
        printf("第一个包含1的元素的下标是%d,它的第一个1是从最低位开始的第%d位。\n", index, index % (sizeof(int) * 8));
    } else {
        printf("数组中没有包含1的元素。\n");
    }

    return 0;
}

可以使用位运算来实现。首先遍历整个数组,查找第一个包含1的元素,然后使用位运算查找该元素二进制表示中的第一个1。

以下是一个示例代码:

#include <stdio.h>

int main() {
    int arr[] = {0b10010000, 0b01000000, 0b00100000, 0b00010000, 0b00001000};
    int n = sizeof(arr) / sizeof(int);

    // 遍历数组,查找第一个包含1的元素
    int i = 0;
    while (i < n && (arr[i] & 1) == 0) {
        i++;
    }

    // 如果数组中没有包含1的元素,输出错误信息
    if (i == n) {
        printf("数组中没有包含1的元素\n");
        return 0;
    }

    // 使用位运算查找二进制表示中的第一个1
    int j = 0;
    while ((arr[i] & (1 << j)) == 0) {
        j++;
    }

    // 输出结果
    printf("第一个包含1的元素是 %d,二进制的第%d位是第一个1\n", arr[i], j + 1);

    return 0;
}


该程序首先定义了一个整数数组 arr,其中包含一些测试用例。然后程序遍历整个数组,查找第一个包含1的元素,如果没有找到就输出错误信息。接下来,程序使用位运算查找该元素二进制表示中的第一个1,并输出结果。注意,由于题目要求从最低位开始查找,因此最终输出的是二进制的第j+1位是第一个1。

思路如下:
定义一个变量bit,初始化为1。
使用循环将bit左移,直到它的值大于数组元素。
检查bit与数组元素的按位与操作是否不为0。如果不为0,说明数组元素中存在1,我们就找到了这个元素。
如果没有找到1,就将bit右移一位,继续搜索下一位

#include <stdio.h>

int main() {
    int arr[] = {0x10, 0x20, 0x30, 0x40};
    int i, j, bit;
    for (i = 0; i < sizeof(arr) / sizeof(int); i++) {
        bit = 1;
        for (j = 0; j < 32; j++) {
            if ((bit & arr[i]) != 0) {
                printf("The first element with 1 is %d, the first 1 is at position %d\n", arr[i], j+1);
                break;
            }
            bit <<= 1;
        }
    }
    return 0;
}

尝试下这个方式看看

#include <stdio.h>

void find_first_element(unsigned int *in, int len, unsigned int *first_elm, int *index)
{
    int i;
    unsigned int *p;

    for(p=in;p<in+len;p++) {
        if(*p) {
            //找到第一个含有1的元素
            unsigned int ch = *p;
            *first_elm = ch;
            
            for(i=0;i<32;i++) {
                unsigned int c=(ch>>i);
                if(c%2) {
                    //找到这个元素二进制的第一个1
                    *index = i+1;
                    break;
                }
                
            }
            break;
        }
    }
}

int main(int argc, char* argv[])
{
    unsigned int testarry[128]={0,0,0,0,0,144};
    unsigned int first_elm;
    int index;
    
    find_first_element(testarry, sizeof(testarry)/sizeof(testarry[0]), &first_elm, &index);
    printf("The first element with 1: %d, the first 1 index:%d\n", first_elm, index);
    
}

该回答引用ChatGPT

如果有疑问可以回复我
以下是一个用 C 语言实现的查找数组中第一个包含1的元素及其二进制表示中的第一个1的位数的示例代码:


#include <stdio.h>
int main() {
    int arr[] = {0, 0, 16, 4, 8, 2};
    int len = sizeof(arr) / sizeof(arr[0]);
    int i, j;
    
    for (i = 0; i < len; i++) {
        if (arr[i] != 0) {
            for (j = 0; j < sizeof(int) * 8; j++) {
                if (arr[i] & (1 << j)) {
                    printf("第一个包含1的元素是:%d,它的二进制表示中第一个1的位数是:%d\n", arr[i], j + 1);
                    return 0;
                }
            }
        }
    }
    printf("未找到包含1的元素\n");
    return 0;
}


以下答案基于ChatGPT与GISer Liu编写:
以下是用C语言实现的代码,可以找出一个数组中第一个含有1的元素,并确定这个元素二进制的第几位是第一个1(从最低位开始)。

#include <stdio.h>

int find_first_one(int arr[], int n) {
    int i, j;
    for (i = 0; i < n; i++) {
        if (arr[i] != 0) { // 如果数组中的元素不为0
            for (j = 0; j < sizeof(int) * 8; j++) { // 遍历这个元素的每一位
                if (arr[i] & (1 << j)) { // 如果这一位是1
                    return (i << 5) + j + 1; // 返回第一个含有1的元素的下标和这个元素二进制的第几位是第一个1
                }
            }
        }
    }
    return -1; // 如果数组中没有任何一个元素含有1,则返回-1
}

int main() {
    int arr[] = {0, 0, 0, 0, 144, 0, 0, 0}; // 假设有这样一个数组
    int index = find_first_one(arr, sizeof(arr) / sizeof(arr[0])); // 调用find_first_one函数
    if (index != -1) {
        printf("第一个含有1的元素的下标是%d,它二进制的第%d位是第一个1(从最低位开始)\n", index / 32, index % 32);
    } else {
        printf("数组中没有任何一个元素含有1\n");
    }
    return 0;
}

这个代码使用了两个for循环。外层循环遍历数组中的每个元素,内层循环遍历这个元素的每一位,直到找到第一个1为止。如果数组中没有任何一个元素含有1,则返回-1。

对于找到第一个含有1的元素的二进制第几位是1,我们将其返回为一个整数。其中,这个整数的前5位是这个元素在数组中的下标,后面的位数是这个元素二进制的第几位是第一个1。例如,假设数组中的第一个元素是10010000,则返回的整数是5 * 32 + 5 + 1 = 166,其中5是第一个含有1的元素的下标,5是这个元素二进制的第几位是第一个1,+1是因为我们从最低位开始计数。

在代码中,我们使用了位运算符&和位运算符<<。&运算符用于将一个二进制数的某一位和1进行逻辑与运算,判断这一位是否为1。<<运算符将一个数的二进制数向左移动若干位,例如1 << j就是将1左移j位。这个操作实际上就是将1的二进制数向左移动j位,再将其转换为十进制数

不知道你这个问题是否已经解决, 如果还没有解决的话:
  • 这个问题的回答你可以参考下: https://ask.csdn.net/questions/1056544
  • 你也可以参考下这篇文章:C语言中利用指针输出二维数组中的第三行元素
  • 除此之外, 这篇博客: C语言二维数组及指针引用中的 2.用指针引用二维数组元素 部分也许能够解决你的问题, 你可以仔细阅读以下内容或者直接跳转源博客中阅读:

    我们先从一个问题的引入进行分析:
    对于字符数组s考虑下面两种指针的引用形式:
    第一种:

    char *p=(char *)s;
    

    这行代码的意义是,将二维数组s的首地址转换成字符指针的类型并赋值给字符指针p,这样一来,指针p指向的就是二维数组s的首元素地址,p+1的操作可以让p每次向后移动一个字符char元素的位置。

    第二种:

    char (*p)[3]=s;
    

    首先理解char (p)[3]的含义:这是一个指针,指向的类型是一个大小为3的一维数组。那么p的值就是数组名的地址,数组名也是地址,所以这是一个指向地址的指针,什么意思呢,意思就是这个指针p中存的是地址的地址,所以是二级指针。那么 * p的意义是取p指向的数组首地址,而 ** p的意义才是数组中第一个元素。

    两种形式指针对二维数组的引用都行得通:

    • 第一种简单笨拙,每次移动一个元素去引用对应的二维数组中的第n个元素。
    • 第二种在明白其意义后则很方便直接指向第几行第几列的元素。

    考虑完这两种指针的意义后,我们分别对上面两种情形执行下面的程序:
    第一种:

    char s[2][3]={'a','b','c','d','e','f'};
    char *p=(char*)s;
    printf("%c",*++p+2);
    

    运行结果如下:

    打印出字符:d
    

    解释:数组名s原本是一个二级地址,但是通过强制类型转换(char *)将其转换为了一个一级地址,可以理解为将原来有层次的存储空间进行了扁平化处理,平铺成了一个很长的连续的一维数组,然后通过移动p去引用,那么我们看 ++p+2的意义,++优先级最高,所以指针p向后移动一个元素指向b,其次的优先级高,*p取出了p指向的元素b,b+2的ascII码为字符d

    第二种:

    char s[2][3]={'a','b','c','d','e','f'};
    char (*p)[3]=s;
    printf("%c",*(*++p+2));
    

    运行结果如下:

    打印出字符:f
    

    解释:char (p)[3]=s;的意义上面已经详细说过了,p指向的是s为首的一维数组中的第一个数组s[0],s[0]是一个一行三列的一维数组,p存放了s[0]的地址。++p的操作让p向后移动一个单元,指向了s[1],然后执行的p操作取出来s[1]的值,s[1]的值是第二列一维数组的首地址,也就是元素d的地址,然后再对*p+2的操作让这个首地址向后移动了两个单元指向了元素f,值为f的地址。最后对其进行 * 操作取出地址对应的值,则结果是元素f


如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^